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_list.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 103 183 56.3 %
Date: 2018-06-14 Functions: 7 12 58.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 <stdio.h>
      22             : #include <string.h>
      23             : #include <sys/stat.h>
      24             : #ifndef _WIN32
      25             : #       include <sys/mman.h>
      26             : #       include <unistd.h>
      27             : #endif
      28             : #include <fcntl.h>
      29             : #include "phpdbg.h"
      30             : #include "phpdbg_list.h"
      31             : #include "phpdbg_utils.h"
      32             : #include "phpdbg_prompt.h"
      33             : #include "php_streams.h"
      34             : #include "zend_exceptions.h"
      35             : 
      36             : ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
      37             : 
      38             : #define PHPDBG_LIST_COMMAND_D(f, h, a, m, l, s, flags) \
      39             :         PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[12], flags)
      40             : 
      41             : const phpdbg_command_t phpdbg_list_commands[] = {
      42             :         PHPDBG_LIST_COMMAND_D(lines,     "lists the specified lines",    'l', list_lines,  NULL, "l", PHPDBG_ASYNC_SAFE),
      43             :         PHPDBG_LIST_COMMAND_D(class,     "lists the specified class",    'c', list_class,  NULL, "s", PHPDBG_ASYNC_SAFE),
      44             :         PHPDBG_LIST_COMMAND_D(method,    "lists the specified method",   'm', list_method, NULL, "m", PHPDBG_ASYNC_SAFE),
      45             :         PHPDBG_LIST_COMMAND_D(func,      "lists the specified function", 'f', list_func,   NULL, "s", PHPDBG_ASYNC_SAFE),
      46             :         PHPDBG_END_COMMAND
      47             : };
      48             : 
      49           1 : PHPDBG_LIST(lines) /* {{{ */
      50             : {
      51           1 :         if (!PHPDBG_G(exec) && !zend_is_executing()) {
      52           0 :                 phpdbg_error("inactive", "type=\"execution\"", "Not executing, and execution context not set");
      53           0 :                 return SUCCESS;
      54             :         }
      55             : 
      56           1 :         switch (param->type) {
      57           1 :                 case NUMERIC_PARAM: {
      58           1 :                         const char *char_file = phpdbg_current_file();
      59           2 :                         zend_string *file = zend_string_init(char_file, strlen(char_file), 0);
      60           1 :                         phpdbg_list_file(file, param->num < 0 ? 1 - param->num : param->num, (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(), 0);
      61           1 :                         efree(file);
      62           1 :                 } break;
      63             : 
      64           0 :                 case FILE_PARAM: {
      65             :                         zend_string *file;
      66             :                         char resolved_path_buf[MAXPATHLEN];
      67           0 :                         const char *abspath = param->file.name;
      68           0 :                         if (VCWD_REALPATH(abspath, resolved_path_buf)) {
      69           0 :                                 abspath = resolved_path_buf;
      70             :                         }
      71           0 :                         file = zend_string_init(abspath, strlen(abspath), 0);
      72           0 :                         phpdbg_list_file(file, param->file.line, 0, 0);
      73             :                         zend_string_release(file);
      74           0 :                 } break;
      75             : 
      76           0 :                 phpdbg_default_switch_case();
      77             :         }
      78             : 
      79           1 :         return SUCCESS;
      80             : } /* }}} */
      81             : 
      82           0 : PHPDBG_LIST(func) /* {{{ */
      83             : {
      84           0 :         phpdbg_list_function_byname(param->str, param->len);
      85             : 
      86           0 :         return SUCCESS;
      87             : } /* }}} */
      88             : 
      89           0 : PHPDBG_LIST(method) /* {{{ */
      90             : {
      91             :         zend_class_entry *ce;
      92             : 
      93           0 :         if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) {
      94             :                 zend_function *function;
      95           0 :                 char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name));
      96             : 
      97           0 :                 if ((function = zend_hash_str_find_ptr(&ce->function_table, lcname, strlen(lcname)))) {
      98           0 :                         phpdbg_list_function(function);
      99             :                 } else {
     100           0 :                         phpdbg_error("list", "type=\"notfound\" method=\"%s::%s\"", "Could not find %s::%s", param->method.class, param->method.name);
     101             :                 }
     102             : 
     103           0 :                 efree(lcname);
     104             :         } else {
     105           0 :                 phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "Could not find the class %s", param->method.class);
     106             :         }
     107             : 
     108           0 :         return SUCCESS;
     109             : } /* }}} */
     110             : 
     111           0 : PHPDBG_LIST(class) /* {{{ */
     112             : {
     113             :         zend_class_entry *ce;
     114             : 
     115           0 :         if (phpdbg_safe_class_lookup(param->str, param->len, &ce) == SUCCESS) {
     116           0 :                 if (ce->type == ZEND_USER_CLASS) {
     117           0 :                         if (ce->info.user.filename) {
     118           0 :                                 phpdbg_list_file(ce->info.user.filename, ce->info.user.line_end - ce->info.user.line_start + 1, ce->info.user.line_start, 0);
     119             :                         } else {
     120           0 :                                 phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ZSTR_VAL(ce->name));
     121             :                         }
     122             :                 } else {
     123           0 :                         phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ZSTR_VAL(ce->name));
     124             :                 }
     125             :         } else {
     126           0 :                 phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "The requested class (%s) could not be found", param->str);
     127             :         }
     128             : 
     129           0 :         return SUCCESS;
     130             : } /* }}} */
     131             : 
     132          67 : void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highlight) /* {{{ */
     133             : {
     134             :         uint line, lastline;
     135             :         phpdbg_file_source *data;
     136             : 
     137          67 :         if (!(data = zend_hash_find_ptr(&PHPDBG_G(file_sources), filename))) {
     138           0 :                 phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file...");
     139           0 :                 return;
     140             :         }
     141             : 
     142          67 :         if (offset < 0) {
     143           0 :                 count += offset;
     144           0 :                 offset = 0;
     145             :         }
     146             : 
     147          67 :         lastline = offset + count;
     148             : 
     149          67 :         if (lastline > data->lines) {
     150          20 :                 lastline = data->lines;
     151             :         }
     152             : 
     153          67 :         phpdbg_xml("<list %r file=\"%s\">", ZSTR_VAL(filename));
     154             : 
     155         312 :         for (line = offset; line < lastline;) {
     156         178 :                 uint linestart = data->line[line++];
     157         178 :                 uint linelen = data->line[line] - linestart;
     158         178 :                 char *buffer = data->buf + linestart;
     159             : 
     160         178 :                 if (!highlight) {
     161           5 :                         phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer);
     162             :                 } else {
     163         173 :                         if (highlight != line) {
     164         107 :                                 phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer);
     165             :                         } else {
     166          66 :                                 phpdbg_write("line", "line=\"%u\" code=\"%.*s\" current=\"current\"", ">%05u: %.*s", line, linelen, buffer);
     167             :                         }
     168             :                 }
     169             : 
     170         178 :                 if (*(buffer + linelen - 1) != '\n' || !linelen) {
     171          25 :                         phpdbg_out("\n");
     172             :                 }
     173             :         }
     174             : 
     175          67 :         phpdbg_xml("</list>");
     176             : } /* }}} */
     177             : 
     178           0 : void phpdbg_list_function(const zend_function *fbc) /* {{{ */
     179             : {
     180             :         const zend_op_array *ops;
     181             : 
     182           0 :         if (fbc->type != ZEND_USER_FUNCTION) {
     183           0 :                 phpdbg_error("list", "type=\"internalfunction\" function=\"%s\"", "The function requested (%s) is not user defined", ZSTR_VAL(fbc->common.function_name));
     184           0 :                 return;
     185             :         }
     186             : 
     187           0 :         ops = (zend_op_array *) fbc;
     188             : 
     189           0 :         phpdbg_list_file(ops->filename, ops->line_end - ops->line_start + 1, ops->line_start, 0);
     190             : } /* }}} */
     191             : 
     192           0 : void phpdbg_list_function_byname(const char *str, size_t len) /* {{{ */
     193             : {
     194           0 :         HashTable *func_table = EG(function_table);
     195             :         zend_function* fbc;
     196           0 :         char *func_name = (char*) str;
     197           0 :         size_t func_name_len = len;
     198             : 
     199             :         /* search active scope if begins with period */
     200           0 :         if (func_name[0] == '.') {
     201           0 :                 zend_class_entry *scope = zend_get_executed_scope();
     202           0 :                 if (scope) {
     203           0 :                         func_name++;
     204           0 :                         func_name_len--;
     205             : 
     206           0 :                         func_table = &scope->function_table;
     207             :                 } else {
     208           0 :                         phpdbg_error("inactive", "type=\"noclasses\"", "No active class");
     209           0 :                         return;
     210             :                 }
     211           0 :         } else if (!EG(function_table)) {
     212           0 :                 phpdbg_error("inactive", "type=\"function_table\"", "No function table loaded");
     213           0 :                 return;
     214             :         } else {
     215           0 :                 func_table = EG(function_table);
     216             :         }
     217             : 
     218             :         /* use lowercase names, case insensitive */
     219           0 :         func_name = zend_str_tolower_dup(func_name, func_name_len);
     220             : 
     221           0 :         phpdbg_try_access {
     222           0 :                 if ((fbc = zend_hash_str_find_ptr(func_table, func_name, func_name_len))) {
     223           0 :                         phpdbg_list_function(fbc);
     224             :                 } else {
     225           0 :                         phpdbg_error("list", "type=\"nofunction\" function=\"%s\"", "Function %s not found", func_name);
     226             :                 }
     227           0 :         } phpdbg_catch_access {
     228           0 :                 phpdbg_error("signalsegv", "function=\"%s\"", "Could not list function %s, invalid data source", func_name);
     229           0 :         } phpdbg_end_try_access();
     230             : 
     231           0 :         efree(func_name);
     232             : } /* }}} */
     233             : 
     234             : /* Note: do not free the original file handler, let original compile_file() or caller do that. Caller may rely on its value to check success */
     235          75 : zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
     236             :         phpdbg_file_source data, *dataptr;
     237             :         zend_file_handle fake;
     238             :         zend_op_array *ret;
     239             :         char *filename;
     240             :         uint line;
     241             :         char *bufptr, *endptr;
     242             : 
     243          75 :         if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) {
     244           0 :                 return PHPDBG_G(compile_file)(file, type);
     245             :         }
     246             : 
     247          75 :         filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
     248             : 
     249          75 :         data.buf = emalloc(data.len + ZEND_MMAP_AHEAD + 1);
     250          75 :         if (data.len > 0) {
     251          75 :                 memcpy(data.buf, bufptr, data.len);
     252             :         }
     253          75 :         memset(data.buf + data.len, 0, ZEND_MMAP_AHEAD + 1);
     254          75 :         data.line[0] = 0;
     255             : 
     256          75 :         memset(&fake, 0, sizeof(fake));
     257          75 :         fake.type = ZEND_HANDLE_MAPPED;
     258          75 :         fake.handle.stream.mmap.buf = data.buf;
     259          75 :         fake.handle.stream.mmap.len = data.len;
     260          75 :         fake.free_filename = 0;
     261          75 :         fake.filename = filename;
     262          75 :         fake.opened_path = file->opened_path;
     263             : 
     264          75 :         *(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data;
     265             : 
     266       10724 :         for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) {
     267       10574 :                 if (*bufptr == '\n') {
     268         790 :                         dataptr->line[++line] = (uint)(bufptr - data.buf) + 1;
     269             :                 }
     270             :         }
     271          75 :         dataptr->lines = ++line;
     272          75 :         dataptr->line[line] = endptr - data.buf;
     273             : 
     274          75 :         ret = PHPDBG_G(compile_file)(&fake, type);
     275             : 
     276          75 :         if (ret == NULL) {
     277           0 :                 efree(data.buf);
     278           0 :                 efree(dataptr);
     279             : 
     280           0 :                 fake.opened_path = NULL;
     281           0 :                 zend_file_handle_dtor(&fake);
     282             : 
     283           0 :                 return NULL;
     284             :         }
     285             : 
     286          75 :         dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line);
     287          75 :         zend_hash_add_ptr(&PHPDBG_G(file_sources), ret->filename, dataptr);
     288          75 :         phpdbg_resolve_pending_file_break(ZSTR_VAL(ret->filename));
     289             : 
     290          75 :         fake.opened_path = NULL;
     291          75 :         zend_file_handle_dtor(&fake);
     292             : 
     293          75 :         return ret;
     294             : }
     295             : 
     296          75 : zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) {
     297          75 :         char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
     298             :         char resolved_path_buf[MAXPATHLEN];
     299             :         zend_op_array *op_array;
     300             :         phpdbg_file_source *dataptr;
     301             : 
     302          75 :         if (VCWD_REALPATH(filename, resolved_path_buf)) {
     303          74 :                 filename = resolved_path_buf;
     304             : 
     305          74 :                 if (file->opened_path) {
     306          74 :                         zend_string_release(file->opened_path);
     307         148 :                         file->opened_path = zend_string_init(filename, strlen(filename), 0);
     308             :                 } else {
     309           0 :                         if (file->free_filename) {
     310           0 :                                 efree((char *) file->filename);
     311             :                         }
     312           0 :                         file->free_filename = 0;
     313           0 :                         file->filename = filename;
     314             :                 }
     315             :         }
     316             : 
     317          75 :         op_array = PHPDBG_G(init_compile_file)(file, type);
     318             : 
     319          75 :         if (op_array == NULL) {
     320           0 :                 return NULL;
     321             :         }
     322             : 
     323         150 :         dataptr = zend_hash_find_ptr(&PHPDBG_G(file_sources), op_array->filename);
     324          75 :         ZEND_ASSERT(dataptr != NULL);
     325             : 
     326          75 :         dataptr->op_array = *op_array;
     327          75 :         if (dataptr->op_array.refcount) {
     328          75 :                 ++*dataptr->op_array.refcount;
     329             :         }
     330             : 
     331          75 :         return op_array;
     332             : }
     333             : 
     334           9 : zend_op_array *phpdbg_compile_string(zval *source_string, char *filename) {
     335             :         zend_string *fake_name;
     336             :         zend_op_array *op_array;
     337             :         phpdbg_file_source *dataptr;
     338             :         uint line;
     339             :         char *bufptr, *endptr;
     340             : 
     341           9 :         if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) {
     342           7 :                 return PHPDBG_G(compile_string)(source_string, filename);
     343             :         }
     344             : 
     345           2 :         dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * Z_STRLEN_P(source_string));
     346           2 :         dataptr->buf = estrndup(Z_STRVAL_P(source_string), Z_STRLEN_P(source_string));
     347           2 :         dataptr->len = Z_STRLEN_P(source_string);
     348           2 :         dataptr->line[0] = 0;
     349          70 :         for (line = 0, bufptr = dataptr->buf - 1, endptr = dataptr->buf + dataptr->len; ++bufptr < endptr;) {
     350          66 :                 if (*bufptr == '\n') {
     351           6 :                         dataptr->line[++line] = (uint)(bufptr - dataptr->buf) + 1;
     352             :                 }
     353             :         }
     354           2 :         dataptr->lines = ++line;
     355           2 :         dataptr->line[line] = endptr - dataptr->buf;
     356             : 
     357           2 :         op_array = PHPDBG_G(compile_string)(source_string, filename);
     358             : 
     359           2 :         if (op_array == NULL) {
     360           0 :                 efree(dataptr->buf);
     361           0 :                 efree(dataptr);
     362           0 :                 return NULL;
     363             :         }
     364             : 
     365           2 :         fake_name = strpprintf(0, "%s%c%p", filename, 0, op_array->opcodes);
     366             : 
     367           2 :         dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line);
     368             :         zend_hash_add_ptr(&PHPDBG_G(file_sources), fake_name, dataptr);
     369             : 
     370             :         zend_string_release(fake_name);
     371             : 
     372           2 :         dataptr->op_array = *op_array;
     373           2 :         if (dataptr->op_array.refcount) {
     374           2 :                 ++*dataptr->op_array.refcount;
     375             :         }
     376             : 
     377           2 :         return op_array;
     378             : }
     379             : 
     380          78 : void phpdbg_init_list(void) {
     381          78 :         PHPDBG_G(compile_file) = zend_compile_file;
     382          78 :         PHPDBG_G(compile_string) = zend_compile_string;
     383          78 :         zend_compile_file = phpdbg_compile_file;
     384          78 :         zend_compile_string = phpdbg_compile_string;
     385          78 : }
     386             : 
     387          78 : void phpdbg_list_update(void) {
     388          78 :         PHPDBG_G(init_compile_file) = zend_compile_file;
     389          78 :         zend_compile_file = phpdbg_init_compile_file;
     390          78 : }

Generated by: LCOV version 1.10

Generated at Thu, 14 Jun 2018 10:45:12 +0000 (5 days ago)

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