Skip to content

Commit 024095f

Browse files
committed
Omit FETCH_THIS in closures
Non-static closures are guaranteed to have $this. The existing comment highlights this, but fails to handle it correctly.
1 parent d2a9edf commit 024095f

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Zend/zend_compile.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ static bool zend_is_not_imported(zend_string *name) {
316316
void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
317317
{
318318
*prev_context = CG(context);
319+
CG(context).prev = CG(context).op_array ? prev_context : NULL;
319320
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
320321
CG(context).vars_size = 0;
321322
CG(context).literals_size = 0;
@@ -2920,11 +2921,21 @@ static bool is_global_var_fetch(zend_ast *ast)
29202921

29212922
static bool this_guaranteed_exists(void) /* {{{ */
29222923
{
2923-
zend_op_array *op_array = CG(active_op_array);
2924-
/* Instance methods always have a $this.
2925-
* This also includes closures that have a scope and use $this. */
2926-
return op_array->scope != NULL
2927-
&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0;
2924+
zend_oparray_context *ctx = &CG(context);
2925+
while (ctx) {
2926+
/* Instance methods always have a $this.
2927+
* This also includes closures that have a scope and use $this. */
2928+
zend_op_array *op_array = ctx->op_array;
2929+
if (op_array->fn_flags & ZEND_ACC_STATIC) {
2930+
return false;
2931+
} else if (op_array->scope) {
2932+
return true;
2933+
} else if (!(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
2934+
return false;
2935+
}
2936+
ctx = ctx->prev;
2937+
}
2938+
return false;
29282939
}
29292940
/* }}} */
29302941

@@ -7870,6 +7881,7 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
78707881
}
78717882

78727883
zend_oparray_context_begin(&orig_oparray_context);
7884+
CG(context).op_array = op_array;
78737885

78747886
{
78757887
/* Push a separator to the loop variable stack */

Zend/zend_compile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ typedef struct _zend_live_range {
190190

191191
/* Compilation context that is different for each op array. */
192192
typedef struct _zend_oparray_context {
193+
struct _zend_oparray_context *prev;
194+
zend_op_array *op_array;
193195
uint32_t opcodes_size;
194196
int vars_size;
195197
int literals_size;

Zend/zend_language_scanner.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ static zend_op_array *zend_compile(int type)
615615

616616
zend_file_context_begin(&original_file_context);
617617
zend_oparray_context_begin(&original_oparray_context);
618+
CG(context).op_array = op_array;
618619
zend_compile_top_stmt(CG(ast));
619620
CG(zend_lineno) = last_lineno;
620621
zend_emit_final_return(type == ZEND_USER_FUNCTION);

0 commit comments

Comments
 (0)