@@ -339,6 +339,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_arra
339339 CG (context ).try_catch_offset = -1 ;
340340 CG (context ).current_brk_cont = -1 ;
341341 CG (context ).last_brk_cont = 0 ;
342+ CG (has_assigned_to_http_response_header ) = false;
342343 CG (context ).brk_cont_array = NULL ;
343344 CG (context ).labels = NULL ;
344345 CG (context ).in_jmp_frameless_branch = false;
@@ -2866,7 +2867,7 @@ static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t f
28662867}
28672868/* }}} */
28682869
2869- static zend_result zend_try_compile_cv (znode * result , zend_ast * ast ) /* {{{ */
2870+ static zend_result zend_try_compile_cv (znode * result , zend_ast * ast , uint32_t type ) /* {{{ */
28702871{
28712872 zend_ast * name_ast = ast -> child [0 ];
28722873 if (name_ast -> kind == ZEND_AST_ZVAL ) {
@@ -2883,6 +2884,16 @@ static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
28832884 return FAILURE ;
28842885 }
28852886
2887+ if (zend_string_equals_literal (name , "http_response_header" )) {
2888+ if (type == BP_VAR_R && !CG (has_assigned_to_http_response_header )) {
2889+ zend_error (E_DEPRECATED ,
2890+ "The predefined locally scoped $http_response_header variable is deprecated,"
2891+ " call http_get_last_response_headers() instead" );
2892+ } else if (type == BP_VAR_W ) {
2893+ CG (has_assigned_to_http_response_header ) = true;
2894+ }
2895+ }
2896+
28862897 result -> op_type = IS_CV ;
28872898 result -> u .op .var = lookup_cv (name );
28882899
@@ -2919,6 +2930,14 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
29192930
29202931 opline -> extended_value = ZEND_FETCH_GLOBAL ;
29212932 } else {
2933+ // TODO: Have a test case for this?
2934+ if (name_node .op_type == IS_CONST
2935+ && type == BP_VAR_R
2936+ && zend_string_equals_literal (Z_STR (name_node .u .constant ), "http_response_header" )) {
2937+ zend_error (E_DEPRECATED ,
2938+ "The predefined locally scoped $http_response_header variable is deprecated,"
2939+ " call http_get_last_response_headers() instead" );
2940+ }
29222941 opline -> extended_value = ZEND_FETCH_LOCAL ;
29232942 }
29242943
@@ -2990,7 +3009,7 @@ static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t t
29903009 result -> op_type = IS_TMP_VAR ;
29913010 }
29923011 return opline ;
2993- } else if (zend_try_compile_cv (result , ast ) == FAILURE ) {
3012+ } else if (zend_try_compile_cv (result , ast , type ) == FAILURE ) {
29943013 return zend_compile_simple_var_no_cv (result , ast , type , delayed );
29953014 }
29963015 return NULL ;
@@ -3416,7 +3435,7 @@ static void zend_compile_expr_with_potential_assign_to_self(
34163435 /* $a[0] = $a should evaluate the right $a first */
34173436 znode cv_node ;
34183437
3419- if (zend_try_compile_cv (& cv_node , expr_ast ) == FAILURE ) {
3438+ if (zend_try_compile_cv (& cv_node , expr_ast , BP_VAR_R ) == FAILURE ) {
34203439 zend_compile_simple_var_no_cv (expr_node , expr_ast , BP_VAR_R , 0 );
34213440 } else {
34223441 zend_emit_op_tmp (expr_node , ZEND_QM_ASSIGN , & cv_node , NULL );
@@ -3437,6 +3456,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
34373456 if (is_this_fetch (var_ast )) {
34383457 zend_error_noreturn (E_COMPILE_ERROR , "Cannot re-assign $this" );
34393458 }
3459+ // TODO: Mark assignment to http_response_header?
34403460
34413461 zend_ensure_writable_variable (var_ast );
34423462
@@ -3506,7 +3526,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
35063526 /* list($a, $b) = $a should evaluate the right $a first */
35073527 znode cv_node ;
35083528
3509- if (zend_try_compile_cv (& cv_node , expr_ast ) == FAILURE ) {
3529+ if (zend_try_compile_cv (& cv_node , expr_ast , BP_VAR_R ) == FAILURE ) {
35103530 zend_compile_simple_var_no_cv (& expr_node , expr_ast , BP_VAR_R , 0 );
35113531 } else {
35123532 zend_emit_op_tmp (& expr_node , ZEND_QM_ASSIGN , & cv_node , NULL );
@@ -3821,7 +3841,7 @@ static uint32_t zend_compile_args(
38213841 opcode = ZEND_SEND_VAR_EX ;
38223842 CG (active_op_array )-> fn_flags |= ZEND_ACC_USES_THIS ;
38233843 break ;
3824- } else if (zend_try_compile_cv (& arg_node , arg ) == SUCCESS ) {
3844+ } else if (zend_try_compile_cv (& arg_node , arg , BP_VAR_R ) == SUCCESS ) {
38253845 opcode = ZEND_SEND_VAR_EX ;
38263846 break ;
38273847 }
@@ -5424,7 +5444,7 @@ static void zend_compile_global_var(zend_ast *ast) /* {{{ */
54245444 // TODO(GLOBALS) Forbid "global $GLOBALS"?
54255445 if (is_this_fetch (var_ast )) {
54265446 zend_error_noreturn (E_COMPILE_ERROR , "Cannot use $this as global variable" );
5427- } else if (zend_try_compile_cv (& result , var_ast ) == SUCCESS ) {
5447+ } else if (zend_try_compile_cv (& result , var_ast , BP_VAR_R ) == SUCCESS ) {
54285448 zend_op * opline = zend_emit_op (NULL , ZEND_BIND_GLOBAL , & result , & name_node );
54295449 opline -> extended_value = zend_alloc_cache_slot ();
54305450 } else {
@@ -5550,7 +5570,7 @@ static void zend_compile_unset(zend_ast *ast) /* {{{ */
55505570 case ZEND_AST_VAR :
55515571 if (is_this_fetch (var_ast )) {
55525572 zend_error_noreturn (E_COMPILE_ERROR , "Cannot unset $this" );
5553- } else if (zend_try_compile_cv (& var_node , var_ast ) == SUCCESS ) {
5573+ } else if (zend_try_compile_cv (& var_node , var_ast , BP_VAR_UNSET ) == SUCCESS ) {
55545574 opline = zend_emit_op (NULL , ZEND_UNSET_CV , & var_node , NULL );
55555575 } else {
55565576 opline = zend_compile_simple_var_no_cv (NULL , var_ast , BP_VAR_UNSET , 0 );
@@ -6113,7 +6133,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */
61136133 if (is_this_fetch (value_ast )) {
61146134 zend_error_noreturn (E_COMPILE_ERROR , "Cannot re-assign $this" );
61156135 } else if (value_ast -> kind == ZEND_AST_VAR &&
6116- zend_try_compile_cv (& value_node , value_ast ) == SUCCESS ) {
6136+ zend_try_compile_cv (& value_node , value_ast , BP_VAR_R ) == SUCCESS ) {
61176137 SET_NODE (opline -> op2 , & value_node );
61186138 } else {
61196139 opline -> op2_type = IS_VAR ;
@@ -10801,7 +10821,7 @@ static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
1080110821 if (is_this_fetch (var_ast )) {
1080210822 opline = zend_emit_op (result , ZEND_ISSET_ISEMPTY_THIS , NULL , NULL );
1080310823 CG (active_op_array )-> fn_flags |= ZEND_ACC_USES_THIS ;
10804- } else if (zend_try_compile_cv (& var_node , var_ast ) == SUCCESS ) {
10824+ } else if (zend_try_compile_cv (& var_node , var_ast , BP_VAR_IS ) == SUCCESS ) {
1080510825 opline = zend_emit_op (result , ZEND_ISSET_ISEMPTY_CV , & var_node , NULL );
1080610826 } else {
1080710827 opline = zend_compile_simple_var_no_cv (result , var_ast , BP_VAR_IS , 0 );
0 commit comments