phpdbg_utils.c 19 KB

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