summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-02-22 10:09:28 +0100
committerNikita Popov <nikita.ppv@gmail.com>2021-02-22 10:11:14 +0100
commitb3f4a3105c7a577baacd25ac7b76a32aa96cd7ca (patch)
tree6f1e100c6b1cfbb96acb888abb4e615d7b7b2762
parentde03bc8eb717657262c63152d52bd63bf715b096 (diff)
downloadphp-git-b3f4a3105c7a577baacd25ac7b76a32aa96cd7ca.tar.gz
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.
-rw-r--r--Zend/tests/invalid_const_class_name.phpt8
-rw-r--r--Zend/zend_compile.c46
2 files changed, 31 insertions, 23 deletions
diff --git a/Zend/tests/invalid_const_class_name.phpt b/Zend/tests/invalid_const_class_name.phpt
new file mode 100644
index 0000000000..bedd74e1df
--- /dev/null
+++ b/Zend/tests/invalid_const_class_name.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Invalid constant class name in nested class constant access
+--FILE--
+<?php
+[]::X::X;
+?>
+--EXPECTF--
+Fatal error: Illegal class name in %s on line %d
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 15bc64783d..5ecaa399bd 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -941,22 +941,35 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
{
char *compound;
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ if (type == ZEND_NAME_FQ) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ if (type == ZEND_NAME_RELATIVE) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
+ return zend_string_copy(name);
+ }
+
if (type == ZEND_NAME_RELATIVE) {
return zend_prefix_with_ns(name);
}
- if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
- /* Remove \ prefix (only relevant if this is a string rather than a label) */
+ if (type == ZEND_NAME_FQ) {
if (ZSTR_VAL(name)[0] == '\\') {
+ /* Remove \ prefix (only relevant if this is a string rather than a label) */
name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
- } else {
- zend_string_addref(name);
- }
- /* Ensure that \self, \parent and \static are not used */
- if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
- zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ return name;
}
- return name;
+
+ return zend_string_copy(name);
}
if (FC(imports)) {
@@ -10078,20 +10091,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
return;
}
- switch (zend_get_class_fetch_type(zend_ast_get_str(class_ast))) {
- case ZEND_FETCH_CLASS_SELF:
- if (!zend_is_scope_known()) {
- return;
- }
- resolved_name = zend_string_copy(CG(active_class_entry)->name);
- break;
- case ZEND_FETCH_CLASS_DEFAULT:
- resolved_name = zend_resolve_class_name_ast(class_ast);
- break;
- default:
- return;
- }
-
+ resolved_name = zend_resolve_class_name_ast(class_ast);
if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
zend_string_release_ex(resolved_name, 0);
return;