You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Time\Duration::__unserialize() accepts a "negative zero" payload. #24505
<?php$payload = 'O:13:"Time\Duration":3:{s:7:"seconds";i:0;s:11:"nanoseconds";i:0;s:8:"negative";b:1;}';
$d = unserialize($payload);
var_dump($d->negative); // expected: exception, or false. actual: truevar_dump(Time\Duration::compare($d, Time\Duration::fromSeconds(0))); // int(0)var_dump($d->absolute()->negative); // actual: true (absolute() of a value is still "negative")echojson_encode($d), "\n"; // actual: {"seconds":0,"nanoseconds":0,"negative":true}echoserialize(Time\Duration::fromSeconds(0)->negate()), "\n"; // canonical zero: ...s:8:"negative";b:0;}// For comparison, other non-canonical payloads are rejected:try {
unserialize('O:13:"Time\Duration":3:{s:7:"seconds";i:-1;s:11:"nanoseconds";i:0;s:8:"negative";b:0;}');
} catch (Exception$e) {
echoget_class($e), ': ', $e->getMessage(), "\n";
}
Expected: an exception ("Invalid serialization data for Time\Duration object"), as for the other non-canonical payloads (negative seconds, nanoseconds >= 1e9), or a canonicalized zero with $negative === false. No public factory or arithmetic method can produce a zero duration with $negative === true.
Actual: the object is created with seconds = 0, nanoseconds = 0, negative = true. compare() and == treat it as zero, but the public $negative property, json_encode(), serialize() and absolute() all expose the non-canonical sign.
Activity
NickSdot commentedon Oct 22, 2026
Heads up, wrong info sneaked into the "PHP Version" section.
azjezz commentedon Oct 22, 2026
@NickSdot Thanks! fixed.
TimWolla commentedon Oct 23, 2026
Should already be fixed with
#24356.