1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  Fix crashes when trying to instantiate uninstantiable classes via date static constructors
This commit is contained in:
Niels Dossche
2025-11-06 21:29:54 +01:00
2 changed files with 112 additions and 10 deletions

View File

@@ -1486,7 +1486,8 @@ static void create_date_period_datetime(timelib_time *datetime, zend_class_entry
if (datetime) {
php_date_obj *date_obj;
object_init_ex(zv, ce);
zend_result result = object_init_ex(zv, ce);
ZEND_ASSERT(result == SUCCESS && "should succeed as it reuses an existing object's ce");
date_obj = Z_PHPDATE_P(zv);
date_obj->time = timelib_time_clone(datetime);
} else {
@@ -2318,6 +2319,7 @@ static void add_common_properties(HashTable *myht, zend_object *zobj)
}
/* Advanced Interface */
/* TODO: remove this API because it is unsafe to use as-is, as it does not propagate the failure/success status. */
PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
{
object_init_ex(object, pce);
@@ -2595,7 +2597,9 @@ PHP_FUNCTION(date_create_from_format)
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) {
RETURN_THROWS();
}
if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) {
zval_ptr_dtor(return_value);
RETURN_FALSE;
@@ -2617,7 +2621,9 @@ PHP_FUNCTION(date_create_immutable_from_format)
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) {
RETURN_THROWS();
}
if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) {
zval_ptr_dtor(return_value);
RETURN_FALSE;
@@ -2673,7 +2679,9 @@ PHP_METHOD(DateTime, createFromImmutable)
old_obj = Z_PHPDATE_P(datetimeimmutable_object);
DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeimmutable_object));
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) {
RETURN_THROWS();
}
new_obj = Z_PHPDATE_P(return_value);
new_obj->time = timelib_time_clone(old_obj->time);
@@ -2694,7 +2702,9 @@ PHP_METHOD(DateTime, createFromInterface)
old_obj = Z_PHPDATE_P(datetimeinterface_object);
DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object));
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) {
RETURN_THROWS();
}
new_obj = Z_PHPDATE_P(return_value);
new_obj->time = timelib_time_clone(old_obj->time);
@@ -2712,7 +2722,9 @@ PHP_METHOD(DateTime, createFromTimestamp)
Z_PARAM_NUMBER(value)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, &new_object);
if (object_init_ex(&new_object, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date) != SUCCESS) {
RETURN_THROWS();
}
new_dateobj = Z_PHPDATE_P(&new_object);
switch (Z_TYPE_P(value)) {
@@ -2748,7 +2760,9 @@ PHP_METHOD(DateTimeImmutable, createFromMutable)
old_obj = Z_PHPDATE_P(datetime_object);
DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetime_object));
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) {
RETURN_THROWS();
}
new_obj = Z_PHPDATE_P(return_value);
new_obj->time = timelib_time_clone(old_obj->time);
@@ -2769,7 +2783,9 @@ PHP_METHOD(DateTimeImmutable, createFromInterface)
old_obj = Z_PHPDATE_P(datetimeinterface_object);
DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object));
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) {
RETURN_THROWS();
}
new_obj = Z_PHPDATE_P(return_value);
new_obj->time = timelib_time_clone(old_obj->time);
@@ -2787,7 +2803,9 @@ PHP_METHOD(DateTimeImmutable, createFromTimestamp)
Z_PARAM_NUMBER(value)
ZEND_PARSE_PARAMETERS_END();
php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, &new_object);
if (object_init_ex(&new_object, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable) != SUCCESS) {
RETURN_THROWS();
}
new_dateobj = Z_PHPDATE_P(&new_object);
switch (Z_TYPE_P(value)) {
@@ -5108,7 +5126,9 @@ PHP_METHOD(DatePeriod, createFromISO8601String)
Z_PARAM_LONG(options)
ZEND_PARSE_PARAMETERS_END();
object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period);
if (object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period) != SUCCESS) {
RETURN_THROWS();
}
dpobj = Z_PHPPERIOD_P(return_value);
dpobj->current = NULL;

View File

@@ -0,0 +1,82 @@
--TEST--
Instantiating uninstantiable classes via static constructors
--FILE--
<?php
abstract class MyDatePeriod extends DatePeriod {
public abstract function foo();
}
abstract class MyDateTime extends DateTime {
public abstract function foo();
}
abstract class MyDateTimeImmutable extends DateTimeImmutable {
public abstract function foo();
}
try {
MyDatePeriod::createFromISO8601String('R5');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTime::createFromFormat('Y-m-d', '2025-01-01');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTime::createFromImmutable(new DateTimeImmutable());
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTime::createFromInterface(new DateTimeImmutable());
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTime::createFromTimestamp(0);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTimeImmutable::createFromFormat('Y-m-d', '2025-01-01');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTimeImmutable::createFromMutable(new DateTime());
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTimeImmutable::createFromInterface(new DateTime());
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
MyDateTimeImmutable::createFromTimestamp(0);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Cannot instantiate abstract class MyDatePeriod
Cannot instantiate abstract class MyDateTime
Cannot instantiate abstract class MyDateTime
Cannot instantiate abstract class MyDateTime
Cannot instantiate abstract class MyDateTime
Cannot instantiate abstract class MyDateTimeImmutable
Cannot instantiate abstract class MyDateTimeImmutable
Cannot instantiate abstract class MyDateTimeImmutable
Cannot instantiate abstract class MyDateTimeImmutable