@@ -2221,7 +2221,7 @@ static void zend_gc_check_root_tmpvars(void) {
2221
2221
return ;
2222
2222
}
2223
2223
2224
- if (ZEND_USER_CODE (ex -> func -> type )) {
2224
+ if (ex -> func && ZEND_USER_CODE (ex -> func -> type )) {
2225
2225
const zend_op * op = ex -> opline ;
2226
2226
if (op -> result_type & (IS_VAR | IS_TMP_VAR )) {
2227
2227
switch (op -> opcode ) {
@@ -2249,7 +2249,29 @@ static void zend_gc_check_root_tmpvars(void) {
2249
2249
2250
2250
for (; ex ; ex = ex -> prev_execute_data ) {
2251
2251
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
+
2253
2275
continue ;
2254
2276
}
2255
2277
@@ -2282,7 +2304,7 @@ static void zend_gc_remove_root_tmpvars(void) {
2282
2304
return ;
2283
2305
}
2284
2306
2285
- if (ZEND_USER_CODE (ex -> func -> type )) {
2307
+ if (ex -> func && ZEND_USER_CODE (ex -> func -> type )) {
2286
2308
const zend_op * op = ex -> opline ;
2287
2309
if (op -> result_type & (IS_VAR | IS_TMP_VAR )) {
2288
2310
switch (op -> opcode ) {
@@ -2310,7 +2332,29 @@ static void zend_gc_remove_root_tmpvars(void) {
2310
2332
2311
2333
for (; ex ; ex = ex -> prev_execute_data ) {
2312
2334
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
+
2314
2358
continue ;
2315
2359
}
2316
2360
0 commit comments