Skip to content

Commit

Permalink
Add missing returns in ext/date for PHP 8.3+ (#15735)
Browse files Browse the repository at this point in the history
Issues originally found in #15598
  • Loading branch information
kocsismate committed Sep 14, 2024
1 parent a08d326 commit cb69900
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 5 deletions.
20 changes: 15 additions & 5 deletions ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ static void date_throw_uninitialized_error(zend_class_entry *ce)
}
if (ce_ptr->type != ZEND_INTERNAL_CLASS) {
zend_throw_error(date_ce_date_object_error, "Object of type %s not been correctly initialized by calling parent::__construct() in its constructor", ZSTR_VAL(ce->name));
return;
}
zend_throw_error(date_ce_date_object_error, "Object of type %s (inheriting %s) has not been correctly initialized by calling parent::__construct() in its constructor", ZSTR_VAL(ce->name), ZSTR_VAL(ce_ptr->name));
}
Expand Down Expand Up @@ -3872,6 +3873,7 @@ PHP_METHOD(DateTimeZone, __construct)
if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz), &exception_message)) {
zend_throw_exception_ex(date_ce_date_invalid_timezone_exception, 0, "DateTimeZone::__construct(): %s", exception_message);
efree(exception_message);
RETURN_THROWS();
}
}
/* }}} */
Expand Down Expand Up @@ -4429,11 +4431,6 @@ PHP_METHOD(DateInterval, __construct)

static void php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht) /* {{{ */
{
/* If ->diff is already set, then we need to free it first */
if ((*intobj)->diff) {
timelib_rel_time_dtor((*intobj)->diff);
}

/* If we have a date_string, use that instead */
zval *date_str = zend_hash_str_find(myht, "date_string", strlen("date_string"));
if (date_str && Z_TYPE_P(date_str) == IS_STRING) {
Expand All @@ -4448,6 +4445,14 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte
Z_STRVAL_P(date_str),
err->error_messages[0].position,
err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message);
timelib_time_dtor(time);
timelib_error_container_dtor(err);
return;
}

/* If ->diff is already set, then we need to free it first */
if ((*intobj)->diff) {
timelib_rel_time_dtor((*intobj)->diff);
}

(*intobj)->diff = timelib_rel_time_clone(&time->relative);
Expand All @@ -4462,6 +4467,11 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte
return;
}

/* If ->diff is already set, then we need to free it first */
if ((*intobj)->diff) {
timelib_rel_time_dtor((*intobj)->diff);
}

/* Set new value */
(*intobj)->diff = timelib_rel_time_ctor();

Expand Down
68 changes: 68 additions & 0 deletions ext/date/tests/date_interval_set_state_error1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
--TEST--
Test that DateInterval::__unserialize() doesn't modify state in case of a date_string format error
--FILE--
<?php

$interval = new DateInterval("P1Y1DT1H1M");

var_dump($interval);

try {
$interval->__unserialize(
[
"date_string" => "wrong",
]
);
} catch (Error $e) {
echo $e->getMessage() . "\n";
}

var_dump($interval);

?>
--EXPECTF--
object(DateInterval)#%d (%d) {
["y"]=>
int(1)
["m"]=>
int(0)
["d"]=>
int(1)
["h"]=>
int(1)
["i"]=>
int(1)
["s"]=>
int(0)
["f"]=>
float(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
["from_string"]=>
bool(false)
}
Unknown or bad format (wrong) at position 0 (w) while unserializing: The timezone could not be found in the database
object(DateInterval)#%d (%d) {
["y"]=>
int(1)
["m"]=>
int(0)
["d"]=>
int(1)
["h"]=>
int(1)
["i"]=>
int(1)
["s"]=>
int(0)
["f"]=>
float(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
["from_string"]=>
bool(false)
}

0 comments on commit cb69900

Please sign in to comment.