Skip to content

Commit 866adb1

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). zend_dval_to_lval() does this by returning `0` instead of triggering UB. This way we can avoid setting the invalid marker, which doesn't work as expected anyway. We must not do that only for unserialization, but also when the property is set in the first place. We need to adapt some of the existing tests wrt. this behavior. In particular, we check for an arbitrary value in bug79015.phpt, to cater to differences between 32bit and 64bit architectures. Closes GH-7575.
1 parent 3657693 commit 866adb1

File tree

8 files changed

+27
-11
lines changed

8 files changed

+27
-11
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Fixed bug #81518 (Header injection via default_mimetype / default_charset).
77
(cmb)
88

9+
- Date:
10+
. Fixed bug #81500 (Interval serialization regression since 7.3.14 / 7.4.2).
11+
(cmb)
12+
913
- MySQLi:
1014
. Fixed bug #81494 (Stopped unbuffered query does not throw error). (Nikita)
1115

ext/date/php_date.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4331,7 +4331,7 @@ 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+
obj->diff->us = zend_dval_to_lval(zval_get_double(value) * 1000000.0);
43354335
break;
43364336
}
43374337
SET_VALUE_FROM_STRUCT(invert, "invert");
@@ -4468,12 +4468,8 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter
44684468
PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1)
44694469
{
44704470
zval *z_arg = zend_hash_str_find(myht, "f", sizeof("f") - 1);
4471-
(*intobj)->diff->us = -1000000;
44724471
if (z_arg) {
4473-
double val = zval_get_double(z_arg) * 1000000;
4474-
if (val >= 0 && val < 1000000) {
4475-
(*intobj)->diff->us = val;
4476-
}
4472+
(*intobj)->diff->us = zend_dval_to_lval(zval_get_double(z_arg) * 1000000.0);
44774473
}
44784474
}
44794475
PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1)

ext/date/tests/bug53437_var3.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ object(DateInterval)#%d (16) {
4444
["have_special_relative"]=>
4545
int(0)
4646
["f"]=>
47-
float(-1)
47+
float(0)
4848
}
4949
==DONE==

ext/date/tests/bug53437_var5.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ object(DateInterval)#%d (16) {
4444
["have_special_relative"]=>
4545
int(0)
4646
["f"]=>
47-
float(-1)
47+
float(0)
4848
}
4949
==DONE==

ext/date/tests/bug73091.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object(DateInterval)#%d (16) {
2828
["s"]=>
2929
int(-1)
3030
["f"]=>
31-
float(-1)
31+
float(0)
3232
["weekday"]=>
3333
int(-1)
3434
["weekday_behavior"]=>

ext/date/tests/bug79015.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object(DateInterval)#%d (16) {
2020
["s"]=>
2121
int(0)
2222
["f"]=>
23-
float(-1)
23+
float(%f)
2424
["weekday"]=>
2525
int(0)
2626
["weekday_behavior"]=>

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)

ext/standard/tests/serialize/bug69425.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ array(2) {
4040
["s"]=>
4141
int(-1)
4242
["f"]=>
43-
float(-1)
43+
float(0)
4444
["weekday"]=>
4545
int(-1)
4646
["weekday_behavior"]=>

0 commit comments

Comments
 (0)