@@ -1257,9 +1257,11 @@ static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC) {
1257
1257
MAKE_STD_ZVAL (arg_array );
1258
1258
array_init (arg_array );
1259
1259
p -= arg_count ;
1260
+
1260
1261
while (-- arg_count >= 0 ) {
1261
1262
arg = (zval * * ) p ++ ;
1262
1263
SEPARATE_ZVAL_TO_MAKE_IS_REF (arg );
1264
+ (* arg )-> refcount ++ ;
1263
1265
add_next_index_zval (arg_array , * arg );
1264
1266
}
1265
1267
return arg_array ;
@@ -1274,9 +1276,12 @@ ZEND_FUNCTION(debug_backtrace)
1274
1276
char * function_name ;
1275
1277
char * filename ;
1276
1278
char * class_name ;
1279
+ char * call_type ;
1277
1280
char * include_filename = NULL ;
1278
1281
zval * stack_frame ;
1279
- void * * cur_arg_pos = EG (argument_stack ).top_element - 2 ;
1282
+ void * * cur_arg_pos = EG (argument_stack ).top_element ;
1283
+ int get_args ;
1284
+
1280
1285
1281
1286
if (ZEND_NUM_ARGS ()) {
1282
1287
WRONG_PARAM_COUNT ;
@@ -1286,6 +1291,7 @@ ZEND_FUNCTION(debug_backtrace)
1286
1291
1287
1292
/* skip debug_backtrace() */
1288
1293
ptr = ptr -> prev_execute_data ;
1294
+ cur_arg_pos -= 2 ;
1289
1295
1290
1296
if (ptr && cur_arg_pos [-1 ]) {
1291
1297
zend_error (E_ERROR , "debug_backtrace(): Can't be used as a function parameter" );
@@ -1297,21 +1303,20 @@ ZEND_FUNCTION(debug_backtrace)
1297
1303
MAKE_STD_ZVAL (stack_frame );
1298
1304
array_init (stack_frame );
1299
1305
1300
- class_name = NULL ;
1301
-
1302
- if (ptr -> object ) {
1303
- class_name = Z_OBJCE (* ptr -> object )-> name ;
1304
- add_assoc_string_ex (stack_frame , "type" , sizeof ("type" ), "->" , 1 );
1305
- } else if (ptr -> function_state .function -> common .scope ) {
1306
- class_name = ptr -> function_state .function -> common .scope -> name ;
1307
- add_assoc_string_ex (stack_frame , "type" , sizeof ("type" ), "::" , 1 );
1308
- }
1309
-
1310
1306
if (ptr -> op_array ) {
1311
1307
filename = ptr -> op_array -> filename ;
1312
1308
lineno = ptr -> opline -> lineno ;
1313
1309
add_assoc_string_ex (stack_frame , "file" , sizeof ("file" ), filename , 1 );
1314
1310
add_assoc_long_ex (stack_frame , "line" , sizeof ("line" ), lineno );
1311
+
1312
+ /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
1313
+ * and debug_baktrace() might have been called by the error_handler. in this case we don't
1314
+ * want to pop anything of the argument-stack */
1315
+ if ((ptr -> opline -> opcode == ZEND_DO_FCALL_BY_NAME ) || (ptr -> opline -> opcode == ZEND_DO_FCALL )) {
1316
+ get_args = 1 ;
1317
+ } else {
1318
+ get_args = 0 ;
1319
+ }
1315
1320
} else {
1316
1321
filename = NULL ;
1317
1322
}
@@ -1321,11 +1326,25 @@ ZEND_FUNCTION(debug_backtrace)
1321
1326
if (function_name ) {
1322
1327
add_assoc_string_ex (stack_frame , "function" , sizeof ("function" ), function_name , 1 );
1323
1328
1329
+ if (ptr -> object ) {
1330
+ class_name = Z_OBJCE (* ptr -> object )-> name ;
1331
+ call_type = "->" ;
1332
+ add_assoc_string_ex (stack_frame , "type" , sizeof ("type" ), "->" , 1 );
1333
+ } else if (ptr -> function_state .function -> common .scope ) {
1334
+ class_name = ptr -> function_state .function -> common .scope -> name ;
1335
+ call_type = "::" ;
1336
+ } else {
1337
+ class_name = NULL ;
1338
+ }
1339
+
1324
1340
if (class_name ) {
1325
1341
add_assoc_string_ex (stack_frame , "class" , sizeof ("class" ), class_name , 1 );
1342
+ add_assoc_string_ex (stack_frame , "type" , sizeof ("type" ), call_type , 1 );
1326
1343
}
1327
1344
1328
- add_assoc_zval_ex (stack_frame , "args" , sizeof ("args" ), debug_backtrace_get_args (& cur_arg_pos TSRMLS_CC ));
1345
+ if (get_args ) {
1346
+ add_assoc_zval_ex (stack_frame , "args" , sizeof ("args" ), debug_backtrace_get_args (& cur_arg_pos TSRMLS_CC ));
1347
+ }
1329
1348
} else {
1330
1349
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
1331
1350
zend_bool build_filename_arg = 1 ;
@@ -1348,9 +1367,10 @@ ZEND_FUNCTION(debug_backtrace)
1348
1367
function_name = "require_once" ;
1349
1368
break ;
1350
1369
default :
1351
- function_name = "unknown" ;
1370
+ /* this can actually happen if you use debug_backtrace() in your error_handler and
1371
+ * you're in the top-scope */
1372
+ function_name = "unknown" ;
1352
1373
build_filename_arg = 0 ;
1353
- zend_error (E_ERROR , "debug_backtrece(): unable to find function-name. Please report a bug." );
1354
1374
break ;
1355
1375
}
1356
1376
0 commit comments