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 (p && 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 name = emalloc(i + keylen + 2);
507 namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, (int) (keylen - (propkey - key)), propkey, input[len - 1] == ']'?"]":"");
508 if (!strkey) {
509 efree(key);
510 }
511
512 ret = callback(name, namelen, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
513 } else retry_ref: if (Z_TYPE_P(zv) == IS_OBJECT) {
514 if (step_cb) {
515 char *name = estrndup(input, i);
516 char *keyname = estrndup(last_index, index_len);
517
518 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
519 }
520
521 phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_P(zv), i, callback, step_cb, silent, arg);
522 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
523 if (step_cb) {
524 char *name = estrndup(input, i);
525 char *keyname = estrndup(last_index, index_len);
526
527 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
528 }
529
530 phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_P(zv), i, callback, step_cb, silent, arg);
531 } else if (Z_ISREF_P(zv)) {
532 if (step_cb) {
533 char *name = estrndup(input, i);
534 char *keyname = estrndup(last_index, index_len);
535
536 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
537 }
538
539 ZVAL_DEREF(zv);
540 goto retry_ref;
541 } else {
542 /* Ignore silently */
543 }
544 } ZEND_HASH_FOREACH_END();
545 return ret;
546 } else if (new_index) {
547 char last_chr = last_index[index_len];
548 last_index[index_len] = 0;
549 if (!(zv = zend_symtable_str_find(parent, last_index, index_len))) {
550 if (!silent) {
551 phpdbg_error("%.*s is undefined", (int) (input[i] == ']' ? i + 1 : i), input);
552 }
553 return FAILURE;
554 }
555 while (Z_TYPE_P(zv) == IS_INDIRECT) {
556 zv = Z_INDIRECT_P(zv);
557 }
558
559 last_index[index_len] = last_chr;
560 if (i == len) {
561 char *name = estrndup(input, i);
562 char *keyname = estrndup(last_index, index_len);
563
564 ret = callback(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
565 } else retry_ref_end: if (Z_TYPE_P(zv) == IS_OBJECT) {
566 if (step_cb) {
567 char *name = estrndup(input, i);
568 char *keyname = estrndup(last_index, index_len);
569
570 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
571 }
572
573 parent = Z_OBJPROP_P(zv);
574 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
575 if (step_cb) {
576 char *name = estrndup(input, i);
577 char *keyname = estrndup(last_index, index_len);
578
579 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
580 }
581
582 parent = Z_ARRVAL_P(zv);
583 } else if (Z_ISREF_P(zv)) {
584 if (step_cb) {
585 char *name = estrndup(input, i);
586 char *keyname = estrndup(last_index, index_len);
587
588 ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
589 }
590
591 ZVAL_DEREF(zv);
592 goto retry_ref_end;
593 } else {
594 phpdbg_error("%.*s is nor an array nor an object", (int) (input[i] == '>' ? i - 1 : i), input);
595 return FAILURE;
596 }
597 index_len = 0;
598 }
599 }
600
601 return ret;
602 error:
603 phpdbg_error("Malformed input");
604 return FAILURE;
605 }
606
phpdbg_is_auto_global(char * name,int len)607 int phpdbg_is_auto_global(char *name, int len) {
608 return zend_is_auto_global_str(name, len);
609 }
610
phpdbg_check_caught_ex(zend_execute_data * execute_data,zend_object * exception)611 PHPDBG_API bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_object *exception) {
612 const zend_op *op;
613 zend_op *cur;
614 uint32_t op_num, i;
615 zend_op_array *op_array = &execute_data->func->op_array;
616
617 if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3) {
618 op = EG(opline_before_exception);
619 } else {
620 op = execute_data->opline;
621 }
622
623 op_num = op - op_array->opcodes;
624
625 for (i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op <= op_num; i++) {
626 uint32_t catch = op_array->try_catch_array[i].catch_op, finally = op_array->try_catch_array[i].finally_op;
627 if (op_num <= catch || op_num <= finally) {
628 if (finally) {
629 return 1;
630 }
631
632 cur = &op_array->opcodes[catch];
633 while (1) {
634 zend_class_entry *ce;
635
636 if (!(ce = CACHED_PTR(cur->extended_value & ~ZEND_LAST_CATCH))) {
637 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);
638 CACHE_PTR(cur->extended_value & ~ZEND_LAST_CATCH, ce);
639 }
640
641 if (ce == exception->ce || (ce && instanceof_function(exception->ce, ce))) {
642 return 1;
643 }
644
645 if (cur->extended_value & ZEND_LAST_CATCH) {
646 return 0;
647 }
648
649 cur = OP_JMP_ADDR(cur, cur->op2);
650 }
651
652 return 0;
653 }
654 }
655
656 return op->opcode == ZEND_CATCH;
657 }
658
phpdbg_short_zval_print(zval * zv,int maxlen)659 char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */
660 {
661 char *decode = NULL;
662
663 switch (Z_TYPE_P(zv)) {
664 case IS_UNDEF:
665 decode = estrdup("");
666 break;
667 case IS_NULL:
668 decode = estrdup("null");
669 break;
670 case IS_FALSE:
671 decode = estrdup("false");
672 break;
673 case IS_TRUE:
674 decode = estrdup("true");
675 break;
676 case IS_LONG:
677 spprintf(&decode, 0, ZEND_LONG_FMT, Z_LVAL_P(zv));
678 break;
679 case IS_DOUBLE:
680 spprintf(&decode, 0, "%.*G", 14, Z_DVAL_P(zv));
681
682 /* Make sure it looks like a float */
683 if (zend_finite(Z_DVAL_P(zv)) && !strchr(decode, '.')) {
684 size_t len = strlen(decode);
685 char *decode2 = emalloc(len + strlen(".0") + 1);
686 memcpy(decode2, decode, len);
687 decode2[len] = '.';
688 decode2[len+1] = '0';
689 decode2[len+2] = '\0';
690 efree(decode);
691 decode = decode2;
692 }
693 break;
694 case IS_STRING: {
695 int i;
696 zend_string *str = php_addcslashes(Z_STR_P(zv), "\\\"\n\t\0", 5);
697 for (i = 0; i < ZSTR_LEN(str); i++) {
698 if (ZSTR_VAL(str)[i] < 32) {
699 ZSTR_VAL(str)[i] = ' ';
700 }
701 }
702 spprintf(&decode, 0, "\"%.*s\"%c",
703 ZSTR_LEN(str) <= maxlen - 2 ? (int) ZSTR_LEN(str) : (maxlen - 3),
704 ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen - 2 ? 0 : '+');
705 zend_string_release(str);
706 } break;
707 case IS_RESOURCE:
708 spprintf(&decode, 0, "Rsrc #" ZEND_LONG_FMT, Z_RES_HANDLE_P(zv));
709 break;
710 case IS_ARRAY:
711 spprintf(&decode, 0, "array(%d)", zend_hash_num_elements(Z_ARR_P(zv)));
712 break;
713 case IS_OBJECT: {
714 zend_string *str = Z_OBJCE_P(zv)->name;
715 spprintf(&decode, 0, "%.*s%c",
716 ZSTR_LEN(str) <= maxlen ? (int) ZSTR_LEN(str) : maxlen - 1,
717 ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen ? 0 : '+');
718 break;
719 }
720 case IS_CONSTANT_AST: {
721 zend_ast *ast = Z_ASTVAL_P(zv);
722
723 if (ast->kind == ZEND_AST_CONSTANT
724 || ast->kind == ZEND_AST_CONSTANT_CLASS
725 || ast->kind == ZEND_AST_CLASS_CONST) {
726 decode = estrdup("<constant>");
727 } else {
728 decode = estrdup("<ast>");
729 }
730 break;
731 }
732 default:
733 spprintf(&decode, 0, "unknown type: %d", Z_TYPE_P(zv));
734 break;
735 }
736
737 return decode;
738 } /* }}} */
739