Skip to content

Commit 1f8907c

Browse files
committed
ext/uri: avoid shutdown abort for lazy enum alias
1 parent 17579b4 commit 1f8907c

2 files changed

Lines changed: 70 additions & 30 deletions

File tree

ext/uri/php_uri.c

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,13 +1109,15 @@ PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser)
11091109

11101110
zend_string_release_ex(key, true);
11111111

1112-
return result;
1113-
}
1114-
1115-
/* Registers the deprecated, misspelled "InvalidReverseSoldius" class constant as
1116-
* an alias of the correctly spelled UrlValidationErrorType::InvalidReverseSolidus
1117-
* enum case. The typo was shipped in PHP 8.5, so the alias is kept for backwards
1118-
* compatibility.
1112+
return result;
1113+
}
1114+
1115+
#define PHP_URI_WHATWG_INVALID_REVERSE_SOLIDIUS_ALIAS "InvalidReverseSoldius"
1116+
1117+
/* Registers the deprecated, misspelled "InvalidReverseSoldius" class constant as
1118+
* an alias of the correctly spelled UrlValidationErrorType::InvalidReverseSolidus
1119+
* enum case. The typo was shipped in PHP 8.5, so the alias is kept for backwards
1120+
* compatibility.
11191121
*
11201122
* The value is stored as a lazy "self::InvalidReverseSolidus" constant AST instead
11211123
* of an eager enum case object: enum case objects are materialized lazily (the case
@@ -1159,26 +1161,53 @@ static void php_uri_register_invalid_reverse_solidus_alias(zend_class_entry *ce)
11591161
Z_LINENO_P(zend_ast_get_zval(ast->child[1])) = 0;
11601162

11611163
zval alias_value;
1162-
Z_TYPE_INFO(alias_value) = IS_CONSTANT_AST;
1163-
Z_AST(alias_value) = ref;
1164-
1165-
zend_string *alias_name = zend_string_init_interned("InvalidReverseSoldius", sizeof("InvalidReverseSoldius") - 1, true);
1166-
zend_class_constant *alias = zend_declare_class_constant_ex(
1167-
ce, alias_name, &alias_value, ZEND_ACC_PUBLIC | ZEND_ACC_DEPRECATED, NULL);
1168-
1169-
/* Attach #[\Deprecated(since: "8.6", message: "...")] so the deprecation notice
1170-
* directs users to the correctly spelled enum case. */
1164+
Z_TYPE_INFO(alias_value) = IS_CONSTANT_AST;
1165+
Z_AST(alias_value) = ref;
1166+
1167+
zend_string *alias_name = zend_string_init_interned(
1168+
PHP_URI_WHATWG_INVALID_REVERSE_SOLIDIUS_ALIAS,
1169+
sizeof(PHP_URI_WHATWG_INVALID_REVERSE_SOLIDIUS_ALIAS) - 1,
1170+
true);
1171+
zend_class_constant *alias = zend_declare_class_constant_ex(
1172+
ce, alias_name, &alias_value, ZEND_ACC_PUBLIC | ZEND_ACC_DEPRECATED, NULL);
1173+
zend_string_release_ex(alias_name, true);
1174+
1175+
/* Attach #[\Deprecated(since: "8.6", message: "...")] so the deprecation notice
1176+
* directs users to the correctly spelled enum case. */
11711177
zend_attribute *attr = zend_add_class_constant_attribute(ce, alias, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2);
11721178
ZVAL_STR(&attr->args[0].value, zend_string_init("8.6", strlen("8.6"), 1));
11731179
attr->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE);
11741180
ZVAL_STR(&attr->args[1].value, zend_string_init("use Uri\\WhatWg\\UrlValidationErrorType::InvalidReverseSolidus instead", strlen("use Uri\\WhatWg\\UrlValidationErrorType::InvalidReverseSolidus instead"), 1));
1175-
attr->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE);
1176-
}
1177-
1178-
static PHP_MINIT_FUNCTION(uri)
1179-
{
1180-
php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri();
1181-
php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986;
1181+
attr->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE);
1182+
}
1183+
1184+
static void php_uri_cleanup_invalid_reverse_solidus_alias(zend_class_entry *ce)
1185+
{
1186+
if (ce == NULL) {
1187+
return;
1188+
}
1189+
1190+
zend_class_constant *alias = zend_hash_str_find_ptr(
1191+
&ce->constants_table,
1192+
PHP_URI_WHATWG_INVALID_REVERSE_SOLIDIUS_ALIAS,
1193+
sizeof(PHP_URI_WHATWG_INVALID_REVERSE_SOLIDIUS_ALIAS) - 1);
1194+
if (alias == NULL || alias->ce != ce || Z_TYPE(alias->value) != IS_CONSTANT_AST) {
1195+
return;
1196+
}
1197+
1198+
/* This alias uses a regular class-constant AST, while Zend's internal class
1199+
* cleanup currently only expects lazy enum cases to remain as CONSTANT_AST.
1200+
* If the alias was never resolved during runtime, free the extension-owned
1201+
* persistent AST before Zend destroys the internal class entry. */
1202+
ZEND_ASSERT(Z_ASTVAL(alias->value)->kind == ZEND_AST_CLASS_CONST);
1203+
pefree(Z_AST(alias->value), 1);
1204+
ZVAL_UNDEF(&alias->value);
1205+
}
1206+
1207+
static PHP_MINIT_FUNCTION(uri)
1208+
{
1209+
php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri();
1210+
php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986;
11821211
php_uri_ce_rfc3986_uri->default_object_handlers = &object_handlers_rfc3986_uri;
11831212
memcpy(&object_handlers_rfc3986_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
11841213
object_handlers_rfc3986_uri.offset = offsetof(php_uri_object, std);
@@ -1235,13 +1264,14 @@ static PHP_MINFO_FUNCTION(uri)
12351264
#endif
12361265
php_info_print_table_end();
12371266
}
1238-
1239-
static PHP_MSHUTDOWN_FUNCTION(uri)
1240-
{
1241-
zend_hash_destroy(&uri_parsers);
1242-
1243-
return SUCCESS;
1244-
}
1267+
1268+
static PHP_MSHUTDOWN_FUNCTION(uri)
1269+
{
1270+
php_uri_cleanup_invalid_reverse_solidus_alias(php_uri_ce_whatwg_url_validation_error_type);
1271+
zend_hash_destroy(&uri_parsers);
1272+
1273+
return SUCCESS;
1274+
}
12451275

12461276
PHP_RINIT_FUNCTION(uri)
12471277
{
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Uri\WhatWg\UrlValidationErrorType unused deprecated typo alias does not abort shutdown
3+
--EXTENSIONS--
4+
uri
5+
--FILE--
6+
<?php
7+
echo "Done\n";
8+
?>
9+
--EXPECT--
10+
Done

0 commit comments

Comments
 (0)