PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - sapi/phpdbg - phpdbg_utils.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 140 449 31.2 %
Date: 2018-09-22 Functions: 16 30 53.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 22 Sep 2018 10:27:04 +0000 (44 hours ago)

Copyright © 2005-2018 The PHP Group
All rights reserved.