Skip to content

Commit 337deb1

Browse files
committed
Fix #81500: Interval serialization regression since 7.3.14 / 7.4.2
While it may not be desired, `DateInterval::$f` supports negative values, at least with regard to calculations. We still need to guard from assigning double values which are out of range for signed 64bit integers (which would be undefined behavior). While we could restrict this only to values which are actually out of range, the marker for invalid µs is `-1000000`, so we cannot accept smaller numbers. To retain symmetry, we also reject values greater than `1000000`. We must not do that only for unserialization, but also when the property is set in the first place.
1 parent 788a701 commit 337deb1

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

ext/date/php_date.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4331,7 +4331,12 @@ static zval *date_interval_write_property(zval *object, zval *member, zval *valu
43314331
SET_VALUE_FROM_STRUCT(i, "i");
43324332
SET_VALUE_FROM_STRUCT(s, "s");
43334333
if (strcmp(Z_STRVAL_P(member), "f") == 0) {
4334-
obj->diff->us = zval_get_double(value) * 1000000;
4334+
double val = zval_get_double(value) * 1000000;
4335+
if (val > -1000000 && val < 1000000) {
4336+
obj->diff->us = val;
4337+
} else {
4338+
obj->diff->us = -1000000;
4339+
}
43354340
break;
43364341
}
43374342
SET_VALUE_FROM_STRUCT(invert, "invert");
@@ -4471,7 +4476,7 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter
44714476
(*intobj)->diff->us = -1000000;
44724477
if (z_arg) {
44734478
double val = zval_get_double(z_arg) * 1000000;
4474-
if (val >= 0 && val < 1000000) {
4479+
if (val > -1000000 && val < 1000000) {
44754480
(*intobj)->diff->us = val;
44764481
}
44774482
}

ext/date/tests/bug81500.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #81500 (Interval serialization regression since 7.3.14 / 7.4.2)
3+
--FILE--
4+
<?php
5+
$interval = new DateInterval('PT1S');
6+
$interval->f = -0.000001;
7+
var_dump($interval->s, $interval->f);
8+
9+
$interval = unserialize(serialize($interval));
10+
var_dump($interval->s, $interval->f);
11+
?>
12+
--EXPECT--
13+
int(1)
14+
float(-1.0E-6)
15+
int(1)
16+
float(-1.0E-6)

0 commit comments

Comments
 (0)