Skip to content

Commit 8d9a058

Browse files
committed
date: Validate nanoseconds range and normalize negative zero duration
1 parent 3e458e5 commit 8d9a058

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

‎ext/date/tests/time/duration/serialize.phpt‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ try {
4646
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
4747
}
4848

49+
try {
50+
// Nanoseconds that would be truncated to a valid value by a 32-bit conversion (2^32 + 5).
51+
unserialize('O:13:"Time\Duration":3:{s:7:"seconds";i:1;s:11:"nanoseconds";i:4294967301;s:8:"negative";b:0;}');
52+
} catch (Throwable $e) {
53+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
54+
}
55+
56+
// A negative zero duration is normalized to a non-negative one.
57+
$zero = unserialize('O:13:"Time\Duration":3:{s:7:"seconds";i:0;s:11:"nanoseconds";i:0;s:8:"negative";b:1;}');
58+
var_dump($zero->negative);
59+
var_dump(serialize($zero));
60+
var_dump($zero == Time\Duration::fromSeconds(0));
61+
4962
try {
5063
Time\Duration::fromSeconds(1, 1)
5164
->__unserialize([
@@ -69,3 +82,7 @@ Exception: Invalid serialization data for Time\Duration object
6982
Exception: Invalid serialization data for Time\Duration object
7083
Exception: Invalid serialization data for Time\Duration object
7184
Exception: Invalid serialization data for Time\Duration object
85+
bool(false)
86+
string(85) "O:13:"Time\Duration":3:{s:7:"seconds";i:0;s:11:"nanoseconds";i:0;s:8:"negative";b:0;}"
87+
bool(true)
88+
Exception: Invalid serialization data for Time\Duration object

‎ext/date/time_duration.c‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ PHP_METHOD(Time_Duration, __unserialize)
175175
goto fail;
176176
}
177177

178-
/* Verify that both properties are positive, since the timelib_duration_ctor_static() takes unsigned. */
179-
if (Z_LVAL_P(seconds) < 0 || Z_LVAL_P(nanoseconds) < 0) {
178+
/* Verify that both properties are non-negative, since the timelib_duration_ctor_static() takes
179+
* unsigned. */
180+
if (Z_LVAL_P(seconds) < 0 || Z_LVAL_P(nanoseconds) < 0 || Z_LVAL_P(nanoseconds) >= NANOS_IN_SEC) {
180181
goto fail;
181182
}
182183

@@ -191,6 +192,8 @@ PHP_METHOD(Time_Duration, __unserialize)
191192
goto fail;
192193
}
193194

195+
ZVAL_BOOL(negative, duration->duration.negative);
196+
194197
return;
195198

196199
fail:

0 commit comments

Comments
 (0)