Skip to content

Commit 35a36b1

Browse files
committed
Fix comp-time and constant evaluation of dynamic class constant fetch
Fixes GH-10486 Fixes oss-fuzz #55436 Fixes oss-fuzz #55472 Closes GH-10487
1 parent f291d37 commit 35a36b1

9 files changed

+55
-9
lines changed

Zend/Optimizer/compact_literals.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
670670
}
671671
break;
672672
case ZEND_FETCH_CLASS_CONSTANT:
673-
if (opline->op1_type == IS_CONST && opline->op2_type == IS_CONST) {
673+
if (opline->op1_type == IS_CONST
674+
&& opline->op2_type == IS_CONST
675+
&& Z_TYPE(op_array->literals[opline->op2.constant]) == IS_STRING) {
674676
// op1/op2 class_const
675677
opline->extended_value = add_static_slot(&hash, op_array,
676678
opline->op1.constant,

Zend/tests/gh10486.phpt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Assertion error when attempting comp-time eval of dynamic class constant fetch
3+
--FILE--
4+
<?php
5+
y::{5}::y;
6+
?>
7+
--EXPECTF--
8+
Fatal error: Uncaught Error: Class "y" not found in %s:%d
9+
Stack trace:
10+
#0 {main}
11+
thrown in %s on line %d

Zend/tests/gh10486_2.phpt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Assertion error when attempting constant eval of dynamic class constant fetch
3+
--FILE--
4+
<?php
5+
const y = y::{y};
6+
?>
7+
--EXPECTF--
8+
Fatal error: Uncaught Error: Undefined constant "y" in %s:%d
9+
Stack trace:
10+
#0 {main}
11+
thrown in %s on line %d

Zend/zend_ast.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,15 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
834834
case ZEND_AST_CLASS_CONST:
835835
{
836836
zend_string *class_name = zend_ast_get_str(ast->child[0]);
837-
zend_string *const_name = zend_ast_get_str(ast->child[1]);
837+
if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
838+
return FAILURE;
839+
}
840+
if (UNEXPECTED(Z_TYPE(op2) != IS_STRING)) {
841+
zend_invalid_class_constant_type_error(Z_TYPE(op2));
842+
zval_ptr_dtor_nogc(&op2);
843+
return FAILURE;
844+
}
845+
zend_string *const_name = Z_STR(op2);
838846

839847
zend_string *previous_filename;
840848
zend_long previous_lineno;
@@ -852,9 +860,11 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
852860

853861
if (UNEXPECTED(zv == NULL)) {
854862
ZVAL_UNDEF(result);
863+
zval_ptr_dtor_nogc(&op2);
855864
return FAILURE;
856865
}
857866
ZVAL_COPY_OR_DUP(result, zv);
867+
zval_ptr_dtor_nogc(&op2);
858868
break;
859869
}
860870
case ZEND_AST_NEW:

Zend/zend_compile.c

+5
Original file line numberDiff line numberDiff line change
@@ -10742,6 +10742,11 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
1074210742
zend_ast *name_ast;
1074310743
zend_string *resolved_name;
1074410744

10745+
if (UNEXPECTED(ast->child[1]->kind != ZEND_AST_ZVAL
10746+
|| Z_TYPE_P(zend_ast_get_zval(ast->child[1])) != IS_STRING)) {
10747+
return;
10748+
}
10749+
1074510750
zend_eval_const_expr(&ast->child[0]);
1074610751
zend_eval_const_expr(&ast->child[1]);
1074710752

Zend/zend_execute.c

+5
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modificati
894894
ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
895895
}
896896

897+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(zend_uchar type)
898+
{
899+
zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(type));
900+
}
901+
897902
static const zend_class_entry *resolve_single_class_type(zend_string *name, const zend_class_entry *self_ce) {
898903
if (zend_string_equals_literal_ci(name, "self")) {
899904
return self_ce;

Zend/zend_execute.h

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void);
8282
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(const zend_property_info *info);
8383
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(const zend_property_info *info);
8484

85+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(zend_uchar type);
86+
8587
ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg);
8688
ZEND_API ZEND_COLD void zend_verify_arg_error(
8789
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value);

Zend/zend_vm_def.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5922,7 +5922,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
59225922

59235923
constant_zv = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
59245924
if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) {
5925-
zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(Z_TYPE_P(constant_zv)));
5925+
zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv));
59265926
ZVAL_UNDEF(EX_VAR(opline->result.var));
59275927
FREE_OP2();
59285928
HANDLE_EXCEPTION();

Zend/zend_vm_execute.h

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)