Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ext/date/tests/time/duration/serialize.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ try {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
// Nanoseconds that would be truncated to a valid value by a 32-bit conversion (2^32 + 5).
unserialize('O:13:"Time\Duration":3:{s:7:"seconds";i:1;s:11:"nanoseconds";i:4294967301;s:8:"negative";b:0;}');
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
// A negative zero duration is rejected.
unserialize('O:13:"Time\Duration":3:{s:7:"seconds";i:0;s:11:"nanoseconds";i:0;s:8:"negative";b:1;}');
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
Time\Duration::fromSeconds(1, 1)
->__unserialize([
Expand All @@ -69,3 +83,5 @@ Exception: Invalid serialization data for Time\Duration object
Exception: Invalid serialization data for Time\Duration object
Exception: Invalid serialization data for Time\Duration object
Exception: Invalid serialization data for Time\Duration object
Exception: Invalid serialization data for Time\Duration object
Exception: Invalid serialization data for Time\Duration object
13 changes: 12 additions & 1 deletion ext/date/time_duration.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,18 @@ PHP_METHOD(Time_Duration, __unserialize)
goto fail;
}

/* Verify that both properties are positive, since the timelib_duration_ctor_static() takes unsigned. */
/* Verify that both properties are non-negative, since the timelib_duration_ctor_static() takes
* unsigned. */
if (Z_LVAL_P(seconds) < 0 || Z_LVAL_P(nanoseconds) < 0) {
goto fail;
}

/* timelib_duration_ctor_static() takes a uint32_t for nanoseconds, so larger values would
* implicitly wrap around instead of being rejected. */
if (Z_LVAL_P(nanoseconds) >= NANOS_IN_SEC) {
goto fail;
}

int error = timelib_duration_ctor_static(&duration->duration, Z_LVAL_P(seconds), Z_LVAL_P(nanoseconds), Z_TYPE_P(negative) == IS_TRUE);
if (error != TIMELIB_ERROR_NO_ERROR) {
throw_timelib_error(error);
Expand All @@ -191,6 +198,10 @@ PHP_METHOD(Time_Duration, __unserialize)
goto fail;
}

if ((Z_TYPE_P(negative) == IS_TRUE) != duration->duration.negative) {
goto fail;
}

return;

fail:
Expand Down
Loading