Skip to content

Commit b3f4a31

Browse files
committed
Don't resolve special class names
Adjust zend_resolve_class_name() to not resolve special class names. This avoids the need to only call this function after a preliminary check for non-default fetch types. Doing so is somewhat fragile when dynamic class names are involved. Fixes oss-fuzz #31139.
1 parent de03bc8 commit b3f4a31

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Invalid constant class name in nested class constant access
3+
--FILE--
4+
<?php
5+
[]::X::X;
6+
?>
7+
--EXPECTF--
8+
Fatal error: Illegal class name in %s on line %d

Zend/zend_compile.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -941,22 +941,35 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
941941
{
942942
char *compound;
943943

944+
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
945+
if (type == ZEND_NAME_FQ) {
946+
zend_error_noreturn(E_COMPILE_ERROR,
947+
"'\\%s' is an invalid class name", ZSTR_VAL(name));
948+
}
949+
if (type == ZEND_NAME_RELATIVE) {
950+
zend_error_noreturn(E_COMPILE_ERROR,
951+
"'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
952+
}
953+
ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
954+
return zend_string_copy(name);
955+
}
956+
944957
if (type == ZEND_NAME_RELATIVE) {
945958
return zend_prefix_with_ns(name);
946959
}
947960

948-
if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
949-
/* Remove \ prefix (only relevant if this is a string rather than a label) */
961+
if (type == ZEND_NAME_FQ) {
950962
if (ZSTR_VAL(name)[0] == '\\') {
963+
/* Remove \ prefix (only relevant if this is a string rather than a label) */
951964
name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
952-
} else {
953-
zend_string_addref(name);
954-
}
955-
/* Ensure that \self, \parent and \static are not used */
956-
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
957-
zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
965+
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
966+
zend_error_noreturn(E_COMPILE_ERROR,
967+
"'\\%s' is an invalid class name", ZSTR_VAL(name));
968+
}
969+
return name;
958970
}
959-
return name;
971+
972+
return zend_string_copy(name);
960973
}
961974

962975
if (FC(imports)) {
@@ -10078,20 +10091,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
1007810091
return;
1007910092
}
1008010093

10081-
switch (zend_get_class_fetch_type(zend_ast_get_str(class_ast))) {
10082-
case ZEND_FETCH_CLASS_SELF:
10083-
if (!zend_is_scope_known()) {
10084-
return;
10085-
}
10086-
resolved_name = zend_string_copy(CG(active_class_entry)->name);
10087-
break;
10088-
case ZEND_FETCH_CLASS_DEFAULT:
10089-
resolved_name = zend_resolve_class_name_ast(class_ast);
10090-
break;
10091-
default:
10092-
return;
10093-
}
10094-
10094+
resolved_name = zend_resolve_class_name_ast(class_ast);
1009510095
if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
1009610096
zend_string_release_ex(resolved_name, 0);
1009710097
return;

0 commit comments

Comments
 (0)