@@ -2870,7 +2870,7 @@ static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t f
28702870}
28712871/* }}} */
28722872
2873- static zend_result zend_try_compile_cv (znode * result , zend_ast * ast ) /* {{{ */
2873+ static zend_result zend_try_compile_cv (znode * result , zend_ast * ast , uint32_t type ) /* {{{ */
28742874{
28752875 zend_ast * name_ast = ast -> child [0 ];
28762876 if (name_ast -> kind == ZEND_AST_ZVAL ) {
@@ -2890,6 +2890,11 @@ static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
28902890 result -> op_type = IS_CV ;
28912891 result -> u .op .var = lookup_cv (name );
28922892
2893+ // FIXME: Check whether the CV is guaranteed to be declared
2894+ if (type == BP_VAR_R || type == BP_VAR_RW ) {
2895+ zend_emit_op (NULL , ZEND_CHECK_VAR , result , NULL );
2896+ }
2897+
28932898 if (UNEXPECTED (Z_TYPE_P (zv ) != IS_STRING )) {
28942899 zend_string_release_ex (name , 0 );
28952900 }
@@ -2994,7 +2999,7 @@ static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t t
29942999 result -> op_type = IS_TMP_VAR ;
29953000 }
29963001 return opline ;
2997- } else if (zend_try_compile_cv (result , ast ) == FAILURE ) {
3002+ } else if (zend_try_compile_cv (result , ast , type ) == FAILURE ) {
29983003 return zend_compile_simple_var_no_cv (result , ast , type , delayed );
29993004 }
30003005 return NULL ;
@@ -3420,7 +3425,7 @@ static void zend_compile_expr_with_potential_assign_to_self(
34203425 /* $a[0] = $a should evaluate the right $a first */
34213426 znode cv_node ;
34223427
3423- if (zend_try_compile_cv (& cv_node , expr_ast ) == FAILURE ) {
3428+ if (zend_try_compile_cv (& cv_node , expr_ast , BP_VAR_R ) == FAILURE ) {
34243429 zend_compile_simple_var_no_cv (expr_node , expr_ast , BP_VAR_R , 0 );
34253430 } else {
34263431 zend_emit_op_tmp (expr_node , ZEND_QM_ASSIGN , & cv_node , NULL );
@@ -3510,7 +3515,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
35103515 /* list($a, $b) = $a should evaluate the right $a first */
35113516 znode cv_node ;
35123517
3513- if (zend_try_compile_cv (& cv_node , expr_ast ) == FAILURE ) {
3518+ if (zend_try_compile_cv (& cv_node , expr_ast , BP_VAR_R ) == FAILURE ) {
35143519 zend_compile_simple_var_no_cv (& expr_node , expr_ast , BP_VAR_R , 0 );
35153520 } else {
35163521 zend_emit_op_tmp (& expr_node , ZEND_QM_ASSIGN , & cv_node , NULL );
@@ -3825,7 +3830,7 @@ static uint32_t zend_compile_args(
38253830 opcode = ZEND_SEND_VAR_EX ;
38263831 CG (active_op_array )-> fn_flags |= ZEND_ACC_USES_THIS ;
38273832 break ;
3828- } else if (zend_try_compile_cv (& arg_node , arg ) == SUCCESS ) {
3833+ } else if (zend_try_compile_cv (& arg_node , arg , BP_VAR_FUNC_ARG ) == SUCCESS ) {
38293834 opcode = ZEND_SEND_VAR_EX ;
38303835 break ;
38313836 }
@@ -5423,7 +5428,7 @@ static void zend_compile_global_var(zend_ast *ast) /* {{{ */
54235428 // TODO(GLOBALS) Forbid "global $GLOBALS"?
54245429 if (is_this_fetch (var_ast )) {
54255430 zend_error_noreturn (E_COMPILE_ERROR , "Cannot use $this as global variable" );
5426- } else if (zend_try_compile_cv (& result , var_ast ) == SUCCESS ) {
5431+ } else if (zend_try_compile_cv (& result , var_ast , BP_VAR_W ) == SUCCESS ) {
54275432 zend_op * opline = zend_emit_op (NULL , ZEND_BIND_GLOBAL , & result , & name_node );
54285433 opline -> extended_value = zend_alloc_cache_slot ();
54295434 } else {
@@ -5549,7 +5554,7 @@ static void zend_compile_unset(zend_ast *ast) /* {{{ */
55495554 case ZEND_AST_VAR :
55505555 if (is_this_fetch (var_ast )) {
55515556 zend_error_noreturn (E_COMPILE_ERROR , "Cannot unset $this" );
5552- } else if (zend_try_compile_cv (& var_node , var_ast ) == SUCCESS ) {
5557+ } else if (zend_try_compile_cv (& var_node , var_ast , BP_VAR_UNSET ) == SUCCESS ) {
55535558 opline = zend_emit_op (NULL , ZEND_UNSET_CV , & var_node , NULL );
55545559 } else {
55555560 opline = zend_compile_simple_var_no_cv (NULL , var_ast , BP_VAR_UNSET , 0 );
@@ -6074,7 +6079,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */
60746079 if (is_this_fetch (value_ast )) {
60756080 zend_error_noreturn (E_COMPILE_ERROR , "Cannot re-assign $this" );
60766081 } else if (value_ast -> kind == ZEND_AST_VAR &&
6077- zend_try_compile_cv (& value_node , value_ast ) == SUCCESS ) {
6082+ zend_try_compile_cv (& value_node , value_ast , BP_VAR_W ) == SUCCESS ) {
60786083 SET_NODE (opline -> op2 , & value_node );
60796084 } else {
60806085 opline -> op2_type = IS_VAR ;
@@ -10664,7 +10669,7 @@ static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
1066410669 if (is_this_fetch (var_ast )) {
1066510670 opline = zend_emit_op (result , ZEND_ISSET_ISEMPTY_THIS , NULL , NULL );
1066610671 CG (active_op_array )-> fn_flags |= ZEND_ACC_USES_THIS ;
10667- } else if (zend_try_compile_cv (& var_node , var_ast ) == SUCCESS ) {
10672+ } else if (zend_try_compile_cv (& var_node , var_ast , BP_VAR_IS ) == SUCCESS ) {
1066810673 opline = zend_emit_op (result , ZEND_ISSET_ISEMPTY_CV , & var_node , NULL );
1066910674 } else {
1067010675 opline = zend_compile_simple_var_no_cv (result , var_ast , BP_VAR_IS , 0 );
0 commit comments