1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Felipe Pena <felipe@php.net> |
14 | Authors: Joe Watkins <joe.watkins@live.co.uk> |
15 | Authors: Bob Weinand <bwoebi@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "zend.h"
20
21 #include "php.h"
22 #include "phpdbg.h"
23 #include "phpdbg_utils.h"
24 #include "ext/standard/php_string.h"
25
26 /* FASYNC under Solaris */
27 #ifdef HAVE_SYS_FILE_H
28 # include <sys/file.h>
29 #endif
30
31 #ifdef HAVE_SYS_IOCTL_H
32 # include "sys/ioctl.h"
33 # ifndef GWINSZ_IN_SYS_IOCTL
34 # include <termios.h>
35 # endif
36 #endif
37
38 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
39
40 /* {{{ color structures */
41 static const phpdbg_color_t colors[] = {
42 PHPDBG_COLOR_D("none", "0;0"),
43
44 PHPDBG_COLOR_D("white", "0;64"),
45 PHPDBG_COLOR_D("white-bold", "1;64"),
46 PHPDBG_COLOR_D("white-underline", "4;64"),
47 PHPDBG_COLOR_D("red", "0;31"),
48 PHPDBG_COLOR_D("red-bold", "1;31"),
49 PHPDBG_COLOR_D("red-underline", "4;31"),
50 PHPDBG_COLOR_D("green", "0;32"),
51 PHPDBG_COLOR_D("green-bold", "1;32"),
52 PHPDBG_COLOR_D("green-underline", "4;32"),
53 PHPDBG_COLOR_D("yellow", "0;33"),
54 PHPDBG_COLOR_D("yellow-bold", "1;33"),
55 PHPDBG_COLOR_D("yellow-underline", "4;33"),
56 PHPDBG_COLOR_D("blue", "0;34"),
57 PHPDBG_COLOR_D("blue-bold", "1;34"),
58 PHPDBG_COLOR_D("blue-underline", "4;34"),
59 PHPDBG_COLOR_D("purple", "0;35"),
60 PHPDBG_COLOR_D("purple-bold", "1;35"),
61 PHPDBG_COLOR_D("purple-underline", "4;35"),
62 PHPDBG_COLOR_D("cyan", "0;36"),
63 PHPDBG_COLOR_D("cyan-bold", "1;36"),
64 PHPDBG_COLOR_D("cyan-underline", "4;36"),
65 PHPDBG_COLOR_D("black", "0;30"),
66 PHPDBG_COLOR_D("black-bold", "1;30"),
67 PHPDBG_COLOR_D("black-underline", "4;30"),
68 PHPDBG_COLOR_END
69 }; /* }}} */
70
71 /* {{{ */
72 static const phpdbg_element_t elements[] = {
73 PHPDBG_ELEMENT_D("prompt", PHPDBG_COLOR_PROMPT),
74 PHPDBG_ELEMENT_D("error", PHPDBG_COLOR_ERROR),
75 PHPDBG_ELEMENT_D("notice", PHPDBG_COLOR_NOTICE),
76 PHPDBG_ELEMENT_END
77 }; /* }}} */
78
phpdbg_is_numeric(const char * str)79 PHPDBG_API int phpdbg_is_numeric(const char *str) /* {{{ */
80 {
81 if (!str)
82 return 0;
83
84 for (; *str; str++) {
85 if (isspace(*str) || *str == '-') {
86 continue;
87 }
88 return isdigit(*str);
89 }
90 return 0;
91 } /* }}} */
92
phpdbg_is_empty(const char * str)93 PHPDBG_API int phpdbg_is_empty(const char *str) /* {{{ */
94 {
95 if (!str)
96 return 1;
97
98 for (; *str; str++) {
99 if (isspace(*str)) {
100 continue;
101 }
102 return 0;
103 }
104 return 1;
105 } /* }}} */
106
phpdbg_is_addr(const char * str)107 PHPDBG_API int phpdbg_is_addr(const char *str) /* {{{ */
108 {
109 return str[0] && str[1] && memcmp(str, "0x", 2) == 0;
110 } /* }}} */
111
phpdbg_is_class_method(const char * str,size_t len,char ** class,char ** method)112 PHPDBG_API int phpdbg_is_class_method(const char *str, size_t len, char **class, char **method) /* {{{ */
113 {
114 char *sep = NULL;
115
116 if (strstr(str, "#") != NULL)
117 return 0;
118
119 if (strstr(str, " ") != NULL)
120 return 0;
121
122 sep = strstr(str, "::");
123
124 if (!sep || sep == str || sep+2 == str+len-1) {
125 return 0;
126 }
127
128 if (class != NULL) {
129
130 if (str[0] == '\\') {
131 str++;
132 len--;
133 }
134
135 *class = estrndup(str, sep - str);
136 (*class)[sep - str] = 0;
137 }
138
139 if (method != NULL) {
140 *method = estrndup(sep+2, str + len - (sep + 2));
141 }
142
143 return 1;
144 } /* }}} */
145
phpdbg_resolve_path(const char * path)146 PHPDBG_API char *phpdbg_resolve_path(const char *path) /* {{{ */
147 {
148 char resolved_name[MAXPATHLEN];
149
150 if (expand_filepath(path, resolved_name) == NULL) {
151 return NULL;
152 }
153
154 return strdup(resolved_name);
155 } /* }}} */
156
phpdbg_current_file(void)157 PHPDBG_API const char *phpdbg_current_file(void) /* {{{ */
158 {
159 const char *file = zend_get_executed_filename();
160
161 if (memcmp(file, "[no active file]", sizeof("[no active file]")) == 0) {
162 return PHPDBG_G(exec);
163 }
164
165 return file;
166 } /* }}} */
167
phpdbg_get_function(const char * fname,const char * cname)168 PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname) /* {{{ */
169 {
170 zend_function *func = NULL;
171 zend_string *lfname = zend_string_init(fname, strlen(fname), 0);
172 zend_string *tmp = zend_string_tolower(lfname);
173 zend_string_release(lfname);
174 lfname = tmp;
175
176 if (cname) {
177 zend_class_entry *ce;
178 zend_string *lcname = zend_string_init(cname, strlen(cname), 0);
179 tmp = zend_string_tolower(lcname);
180 zend_string_release(lcname);
181 lcname = tmp;
182 ce = zend_lookup_class(lcname);
183
184 zend_string_release(lcname);
185
186 if (ce) {
187 func = zend_hash_find_ptr(&ce->function_table, lfname);
188 }
189 } else {
190 func = zend_hash_find_ptr(EG(function_table), lfname);
191 }
192
193 zend_string_release(lfname);
194 return func;
195 } /* }}} */
196
phpdbg_trim(const char * str,size_t len,size_t * new_len)197 PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len) /* {{{ */
198 {
199 const char *p = str;
200 char *new = NULL;
201
202 while (isspace(*p)) {
203 ++p;
204 --len;
205 }
206
207 while (*p && isspace(*(p + len -1))) {
208 --len;
209 }
210
211 if (len == 0) {
212 new = estrndup("", sizeof(""));
213 *new_len = 0;
214 } else {
215 new = estrndup(p, len);
216 *(new + len) = '\0';
217
218 if (new_len) {
219 *new_len = len;
220 }
221 }
222
223 return new;
224
225 } /* }}} */
226
phpdbg_get_color(const char * name,size_t name_length)227 PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length) /* {{{ */
228 {
229 const phpdbg_color_t *color = colors;
230
231 while (color && color->name) {
232 if (name_length == color->name_length &&
233 memcmp(name, color->name, name_length) == SUCCESS) {
234 phpdbg_debug("phpdbg_get_color(%s, %lu): %s", name, name_length, color->code);
235 return color;
236 }
237 ++color;
238 }
239
240 phpdbg_debug("phpdbg_get_color(%s, %lu): failed", name, name_length);
241
242 return NULL;
243 } /* }}} */
244
phpdbg_set_color(int element,const phpdbg_color_t * color)245 PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color) /* {{{ */
246 {
247 PHPDBG_G(colors)[element] = color;
248 } /* }}} */
249
phpdbg_set_color_ex(int element,const char * name,size_t name_length)250 PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length) /* {{{ */
251 {
252 const phpdbg_color_t *color = phpdbg_get_color(name, name_length);
253
254 if (color) {
255 phpdbg_set_color(element, color);
256 } else PHPDBG_G(colors)[element] = colors;
257 } /* }}} */
258
phpdbg_get_colors(void)259 PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(void) /* {{{ */
260 {
261 return colors;
262 } /* }}} */
263
phpdbg_get_element(const char * name,size_t len)264 PHPDBG_API int phpdbg_get_element(const char *name, size_t len) {
265 const phpdbg_element_t *element = elements;
266
267 while (element && element->name) {
268 if (len == element->name_length) {
269 if (strncasecmp(name, element->name, len) == SUCCESS) {
270 return element->id;
271 }
272 }
273 element++;
274 }
275
276 return PHPDBG_COLOR_INVALID;
277 }
278
phpdbg_set_prompt(const char * prompt)279 PHPDBG_API void phpdbg_set_prompt(const char *prompt) /* {{{ */
280 {
281 /* free formatted prompt */
282 if (PHPDBG_G(prompt)[1]) {
283 free(PHPDBG_G(prompt)[1]);
284 PHPDBG_G(prompt)[1] = NULL;
285 }
286 /* free old prompt */
287 if (PHPDBG_G(prompt)[0]) {
288 free(PHPDBG_G(prompt)[0]);
289 PHPDBG_G(prompt)[0] = NULL;
290 }
291
292 /* copy new prompt */
293 PHPDBG_G(prompt)[0] = strdup(prompt);
294 } /* }}} */
295
phpdbg_get_prompt(void)296 PHPDBG_API const char *phpdbg_get_prompt(void) /* {{{ */
297 {
298 /* find cached prompt */
299 if (PHPDBG_G(prompt)[1]) {
300 return PHPDBG_G(prompt)[1];
301 }
302
303 uint32_t pos = 0,
304 end = strlen(PHPDBG_G(prompt)[0]);
305 bool unicode_warned = false;
306
307 while (pos < end) {
308 if (PHPDBG_G(prompt)[0][pos] & 0x80) {
309 PHPDBG_G(prompt)[0][pos] = '?';
310
311 if (!unicode_warned) {
312 zend_error(E_WARNING,
313 "prompt contains unsupported unicode characters");
314 unicode_warned = true;
315 }
316 }
317 pos++;
318 }
319
320 /* create cached prompt */
321 #ifndef HAVE_LIBEDIT
322 /* TODO: libedit doesn't seems to support coloured prompt */
323 if ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED)) {
324 ZEND_IGNORE_VALUE(asprintf(&PHPDBG_G(prompt)[1], "\033[%sm%s\033[0m ",
325 PHPDBG_G(colors)[PHPDBG_COLOR_PROMPT]->code,
326 PHPDBG_G(prompt)[0]));
327 } else
328 #endif
329 {
330 ZEND_IGNORE_VALUE(asprintf(&PHPDBG_G(prompt)[1], "%s ", PHPDBG_G(prompt)[0]));
331 }
332
333 return PHPDBG_G(prompt)[1];
334 } /* }}} */
335
phpdbg_rebuild_symtable(void)336 int phpdbg_rebuild_symtable(void) {
337 if (!EG(current_execute_data) || !EG(current_execute_data)->func) {
338 phpdbg_error("No active op array!");
339 return FAILURE;
340 }
341
342 if (!zend_rebuild_symbol_table()) {
343 phpdbg_error("No active symbol table!");
344 return FAILURE;
345 }
346
347 return SUCCESS;
348 }
349
phpdbg_get_terminal_width(void)350 PHPDBG_API uint32_t phpdbg_get_terminal_width(void) /* {{{ */
351 {
352 uint32_t columns;
353 #ifdef _WIN32
354 CONSOLE_SCREEN_BUFFER_INFO csbi;
355
356 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
357 columns = (uint32_t) csbi.srWindow.Right - csbi.srWindow.Left + 1;
358 #elif defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ)
359 struct winsize w;
360
361 columns = (uint32_t) ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_col : 80;
362 #else
363 columns = 80;
364 #endif
365 return columns;
366 } /* }}} */
367
phpdbg_get_terminal_height(void)368 PHPDBG_API uint32_t phpdbg_get_terminal_height(void) /* {{{ */
369 {
370 uint32_t lines;
371 #ifdef _WIN32
372 CONSOLE_SCREEN_BUFFER_INFO csbi;
373
374 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
375 lines = (uint32_t) csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
376 } else {
377 lines = 40;
378 }
379 #elif defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ)
380 struct winsize w;
381
382 lines = (uint32_t) ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_row : 40;
383 #else
384 lines = 40;
385 #endif
386 return lines;
387 } /* }}} */
388
phpdbg_set_async_io(int fd)389 PHPDBG_API void phpdbg_set_async_io(int fd) {
390 #if !defined(_WIN32) && defined(FASYNC)
391 int flags;
392 fcntl(STDIN_FILENO, F_SETOWN, getpid());
393 flags = fcntl(STDIN_FILENO, F_GETFL);
394 fcntl(STDIN_FILENO, F_SETFL, flags | FASYNC);
395 #endif
396 }
397
phpdbg_safe_class_lookup(const char * name,int name_length,zend_class_entry ** ce)398 int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce) {
399 if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
400 char *lc_name, *lc_free;
401 int lc_length;
402
403 if (name == NULL || !name_length) {
404 return FAILURE;
405 }
406
407 lc_free = lc_name = emalloc(name_length + 1);
408 zend_str_tolower_copy(lc_name, name, name_length);
409 lc_length = name_length + 1;
410
411 if (lc_name[0] == '\\') {
412 lc_name += 1;
413 lc_length -= 1;
414 }
415
416 phpdbg_try_access {
417 *ce = zend_hash_str_find_ptr(EG(class_table), lc_name, lc_length);
418 } phpdbg_catch_access {
419 phpdbg_error("Could not fetch class %.*s, invalid data source", name_length, name);
420 } phpdbg_end_try_access();
421
422 efree(lc_free);
423 } else {
424 zend_string *str_name = zend_string_init(name, name_length, 0);
425 *ce = zend_lookup_class(str_name);
426 efree(str_name);
427 }
428
429 return *ce ? SUCCESS : FAILURE;
430 }
431
phpdbg_get_property_key(char * key)432 char *phpdbg_get_property_key(char *key) {
433 if (*key != 0) {
434 return key;
435 }
436 return strchr(key + 1, 0) + 1;
437 }
438
phpdbg_parse_variable_arg_wrapper(char * name,size_t len,char * keyname,size_t keylen,HashTable * parent,zval * zv,phpdbg_parse_var_func callback)439 static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, phpdbg_parse_var_func callback) {
440 return callback(name, len, keyname, keylen, parent, zv);
441 }
442
phpdbg_parse_variable(char * input,size_t len,HashTable * parent,size_t i,phpdbg_parse_var_func callback,bool silent)443 PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, bool silent) {
444 return phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_parse_variable_arg_wrapper, NULL, silent, callback);
445 }
446
phpdbg_parse_variable_with_arg(char * input,size_t len,HashTable * parent,size_t i,phpdbg_parse_var_with_arg_func callback,phpdbg_parse_var_with_arg_func step_cb,bool silent,void * arg)447 PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, phpdbg_parse_var_with_arg_func step_cb, bool silent, void *arg) {
448 int ret = FAILURE;
449 bool new_index = 1;
450 char *last_index = NULL;
451 size_t index_len = 0;
452 zval *zv;
453
454 if (len < 2 || *input != '$') {
455 goto error;
456 }
457
458 while (i++ < len) {
459 if (i == len) {
460 new_index = 1;
461 } else {
462 switch (input[i]) {
463 case '[':
464 new_index = 1;
465 break;
466 case ']':
467 break;
468 case '>':
469 if (!last_index) {
470 goto error;
471 }
472 if (last_index[index_len - 1] == '-') {
473 new_index = 1;
474 index_len--;
475 }
476 break;
477
478 default:
479 if (new_index) {
480 last_index = input + i;
481 new_index = 0;
482 }
483 if (input[i - 1] == ']') {
484 goto error;
485 }
486 index_len++;
487 }
488 }
489
490 if (new_index && index_len == 0) {
491 zend_ulong numkey;
492 zend_string *strkey;
493 ZEND_HASH_FOREACH_KEY_VAL_IND(parent, numkey, strkey, zv) {
494 if (i == len || (i == len - 1 && input[len - 1] == ']')) {
495 char *key, *propkey;
496 size_t namelen, keylen;
497 char *name;
498 char *keyname = estrndup(last_index, index_len);
499 if (strkey) {
500 key = ZSTR_VAL(strkey);
501 keylen = ZSTR_LEN(strkey);
502 } else {
503 keylen = spprintf(&key, 0, ZEND_ULONG_FMT, numkey);
504 }
505 propkey = phpdbg_get_property_key(key);
506 namelen = i + keylen + 2;
507 name = emalloc(namelen);
508 namelen = snprintf(name, namelen, "%.*s%.*s%s", (int) i, input, (int) (keylen - (propkey - key)), propkey, input[len - 1] == ']'?"]":"");
509 if (!strkey) {
510 efree(key);
511 }
512
513 ret = callback(name, namelen, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
514 } else retry_ref: if (Z_TYPE_P(zv) == IS_OBJECT) {
515 if (step_cb) {
516 char *name = estrndup(input, i);
517 char *keyname = estrndup(last_index, index_len);
518
519 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
520 }
521
522 phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_P(zv), i, callback, step_cb, silent, arg);
523 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
524 if (step_cb) {
525 char *name = estrndup(input, i);
526 char *keyname = estrndup(last_index, index_len);
527
528 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
529 }
530
531 phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_P(zv), i, callback, step_cb, silent, arg);
532 } else if (Z_ISREF_P(zv)) {
533 if (step_cb) {
534 char *name = estrndup(input, i);
535 char *keyname = estrndup(last_index, index_len);
536
537 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
538 }
539
540 ZVAL_DEREF(zv);
541 goto retry_ref;
542 } else {
543 /* Ignore silently */
544 }
545 } ZEND_HASH_FOREACH_END();
546 return ret;
547 } else if (new_index) {
548 char last_chr = last_index[index_len];
549 last_index[index_len] = 0;
550 if (!(zv = zend_symtable_str_find(parent, last_index, index_len))) {
551 if (!silent) {
552 phpdbg_error("%.*s is undefined", (int) (input[i] == ']' ? i + 1 : i), input);
553 }
554 return FAILURE;
555 }
556 while (Z_TYPE_P(zv) == IS_INDIRECT) {
557 zv = Z_INDIRECT_P(zv);
558 }
559
560 last_index[index_len] = last_chr;
561 if (i == len) {
562 char *name = estrndup(input, i);
563 char *keyname = estrndup(last_index, index_len);
564
565 ret = callback(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
566 } else retry_ref_end: if (Z_TYPE_P(zv) == IS_OBJECT) {
567 if (step_cb) {
568 char *name = estrndup(input, i);
569 char *keyname = estrndup(last_index, index_len);
570
571 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
572 }
573
574 parent = Z_OBJPROP_P(zv);
575 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
576 if (step_cb) {
577 char *name = estrndup(input, i);
578 char *keyname = estrndup(last_index, index_len);
579
580 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
581 }
582
583 parent = Z_ARRVAL_P(zv);
584 } else if (Z_ISREF_P(zv)) {
585 if (step_cb) {
586 char *name = estrndup(input, i);
587 char *keyname = estrndup(last_index, index_len);
588
589 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
590 }
591
592 ZVAL_DEREF(zv);
593 goto retry_ref_end;
594 } else {
595 phpdbg_error("%.*s is nor an array nor an object", (int) (input[i] == '>' ? i - 1 : i), input);
596 return FAILURE;
597 }
598 index_len = 0;
599 }
600 }
601
602 return ret;
603 error:
604 phpdbg_error("Malformed input");
605 return FAILURE;
606 }
607
phpdbg_is_auto_global(char * name,int len)608 int phpdbg_is_auto_global(char *name, int len) {
609 return zend_is_auto_global_str(name, len);
610 }
611
phpdbg_check_caught_ex(zend_execute_data * execute_data,zend_object * exception)612 PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_object *exception) {
613 const zend_op *op;
614 zend_op *cur;
615 uint32_t op_num, i;
616 zend_op_array *op_array = &execute_data->func->op_array;
617
618 if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3 && EG(opline_before_exception)) {
619 op = EG(opline_before_exception);
620 } else {
621 op = execute_data->opline;
622 }
623
624 op_num = op - op_array->opcodes;
625
626 for (i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op <= op_num; i++) {
627 uint32_t catch = op_array->try_catch_array[i].catch_op, finally = op_array->try_catch_array[i].finally_op;
628 if (op_num <= catch || op_num <= finally) {
629 if (finally) {
630 return 1;
631 }
632
633 cur = &op_array->opcodes[catch];
634 while (1) {
635 zend_class_entry *ce;
636
637 if (!(ce = CACHED_PTR(cur->extended_value & ~ZEND_LAST_CATCH))) {
638 ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(cur, cur->op1)), Z_STR_P(RT_CONSTANT(cur, cur->op1) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD);
639 CACHE_PTR(cur->extended_value & ~ZEND_LAST_CATCH, ce);
640 }
641
642 if (ce == exception->ce || (ce && instanceof_function(exception->ce, ce))) {
643 return 1;
644 }
645
646 if (cur->extended_value & ZEND_LAST_CATCH) {
647 return 0;
648 }
649
650 cur = OP_JMP_ADDR(cur, cur->op2);
651 }
652
653 return 0;
654 }
655 }
656
657 return op->opcode == ZEND_CATCH;
658 }
659
phpdbg_short_zval_print(zval * zv,int maxlen)660 char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */
661 {
662 char *decode = NULL;
663
664 switch (Z_TYPE_P(zv)) {
665 case IS_UNDEF:
666 decode = estrdup("");
667 break;
668 case IS_NULL:
669 decode = estrdup("null");
670 break;
671 case IS_FALSE:
672 decode = estrdup("false");
673 break;
674 case IS_TRUE:
675 decode = estrdup("true");
676 break;
677 case IS_LONG:
678 spprintf(&decode, 0, ZEND_LONG_FMT, Z_LVAL_P(zv));
679 break;
680 case IS_DOUBLE:
681 spprintf(&decode, 0, "%.*G", 14, Z_DVAL_P(zv));
682
683 /* Make sure it looks like a float */
684 if (zend_finite(Z_DVAL_P(zv)) && !strchr(decode, '.')) {
685 size_t len = strlen(decode);
686 char *decode2 = emalloc(len + strlen(".0") + 1);
687 memcpy(decode2, decode, len);
688 decode2[len] = '.';
689 decode2[len+1] = '0';
690 decode2[len+2] = '\0';
691 efree(decode);
692 decode = decode2;
693 }
694 break;
695 case IS_STRING: {
696 int i;
697 zend_string *str = php_addcslashes(Z_STR_P(zv), "\\\"\n\t\0", 5);
698 for (i = 0; i < ZSTR_LEN(str); i++) {
699 if (ZSTR_VAL(str)[i] < 32) {
700 ZSTR_VAL(str)[i] = ' ';
701 }
702 }
703 spprintf(&decode, 0, "\"%.*s\"%c",
704 ZSTR_LEN(str) <= maxlen - 2 ? (int) ZSTR_LEN(str) : (maxlen - 3),
705 ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen - 2 ? 0 : '+');
706 zend_string_release(str);
707 } break;
708 case IS_RESOURCE:
709 spprintf(&decode, 0, "Rsrc #" ZEND_LONG_FMT, Z_RES_HANDLE_P(zv));
710 break;
711 case IS_ARRAY:
712 spprintf(&decode, 0, "array(%d)", zend_hash_num_elements(Z_ARR_P(zv)));
713 break;
714 case IS_OBJECT: {
715 zend_string *str = Z_OBJCE_P(zv)->name;
716 spprintf(&decode, 0, "%.*s%c",
717 ZSTR_LEN(str) <= maxlen ? (int) ZSTR_LEN(str) : maxlen - 1,
718 ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen ? 0 : '+');
719 break;
720 }
721 case IS_CONSTANT_AST: {
722 zend_ast *ast = Z_ASTVAL_P(zv);
723
724 if (ast->kind == ZEND_AST_CONSTANT
725 || ast->kind == ZEND_AST_CONSTANT_CLASS
726 || ast->kind == ZEND_AST_CLASS_CONST) {
727 decode = estrdup("<constant>");
728 } else {
729 decode = estrdup("<ast>");
730 }
731 break;
732 }
733 default:
734 spprintf(&decode, 0, "unknown type: %d", Z_TYPE_P(zv));
735 break;
736 }
737
738 return decode;
739 } /* }}} */
740