@@ -2221,7 +2221,7 @@ static void zend_gc_check_root_tmpvars(void) {
22212221 return ;
22222222 }
22232223
2224- if (ZEND_USER_CODE (ex -> func -> type )) {
2224+ if (ex -> func && ZEND_USER_CODE (ex -> func -> type )) {
22252225 const zend_op * op = ex -> opline ;
22262226 if (op -> result_type & (IS_VAR | IS_TMP_VAR )) {
22272227 switch (op -> opcode ) {
@@ -2249,7 +2249,29 @@ static void zend_gc_check_root_tmpvars(void) {
22492249
22502250 for (; ex ; ex = ex -> prev_execute_data ) {
22512251 zend_function * func = ex -> func ;
2252- if (!func || !ZEND_USER_CODE (func -> type )) {
2252+ if (!func ) {
2253+ continue ;
2254+ }
2255+
2256+ if (!ZEND_USER_CODE (func -> type )) {
2257+ /* For internal frames, arguments are not consumed yet, so we must
2258+ * root them. */
2259+ zend_execute_data * caller = ex -> prev_execute_data ;
2260+ if (!caller -> func || !ZEND_USER_CODE (caller -> func -> type )) {
2261+ continue ;
2262+ }
2263+
2264+ uint32_t num_args = ZEND_CALL_NUM_ARGS (ex );
2265+ if (EXPECTED (num_args > 0 )) {
2266+ zval * p = ZEND_CALL_ARG (ex , 1 );
2267+ do {
2268+ if (Z_COLLECTABLE_P (p )) {
2269+ gc_check_possible_root (Z_COUNTED_P (p ));
2270+ }
2271+ p ++ ;
2272+ } while (-- num_args );
2273+ }
2274+
22532275 continue ;
22542276 }
22552277
@@ -2282,7 +2304,7 @@ static void zend_gc_remove_root_tmpvars(void) {
22822304 return ;
22832305 }
22842306
2285- if (ZEND_USER_CODE (ex -> func -> type )) {
2307+ if (ex -> func && ZEND_USER_CODE (ex -> func -> type )) {
22862308 const zend_op * op = ex -> opline ;
22872309 if (op -> result_type & (IS_VAR | IS_TMP_VAR )) {
22882310 switch (op -> opcode ) {
@@ -2310,7 +2332,29 @@ static void zend_gc_remove_root_tmpvars(void) {
23102332
23112333 for (; ex ; ex = ex -> prev_execute_data ) {
23122334 zend_function * func = ex -> func ;
2313- if (!func || !ZEND_USER_CODE (func -> type )) {
2335+ if (!func ) {
2336+ continue ;
2337+ }
2338+
2339+ if (!ZEND_USER_CODE (func -> type )) {
2340+ /* For internal frames, arguments are live, so we should unroot
2341+ * them. */
2342+ zend_execute_data * caller = ex -> prev_execute_data ;
2343+ if (!caller -> func || !ZEND_USER_CODE (caller -> func -> type )) {
2344+ continue ;
2345+ }
2346+
2347+ uint32_t num_args = ZEND_CALL_NUM_ARGS (ex );
2348+ if (EXPECTED (num_args > 0 )) {
2349+ zval * p = ZEND_CALL_ARG (ex , 1 );
2350+ do {
2351+ if (Z_COLLECTABLE_P (p )) {
2352+ GC_REMOVE_FROM_BUFFER (Z_COUNTED_P (p ));
2353+ }
2354+ p ++ ;
2355+ } while (-- num_args );
2356+ }
2357+
23142358 continue ;
23152359 }
23162360
0 commit comments