diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg_list.c')
-rw-r--r-- | sapi/phpdbg/phpdbg_list.c | 185 |
1 files changed, 139 insertions, 46 deletions
diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index c96d8652f0..34e9187f52 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -31,8 +31,9 @@ #include "phpdbg_utils.h" #include "phpdbg_prompt.h" #include "php_streams.h" +#include "zend_exceptions.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) #define PHPDBG_LIST_COMMAND_D(f, h, a, m, l, s, flags) \ PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[12], flags) @@ -61,9 +62,15 @@ PHPDBG_LIST(lines) /* {{{ */ } break; case FILE_PARAM: { - zend_string *file = zend_string_init(param->file.name, strlen(param->file.name), 0); + zend_string *file; + char resolved_path_buf[MAXPATHLEN]; + const char *abspath = param->file.name; + if (VCWD_REALPATH(abspath, resolved_path_buf)) { + abspath = resolved_path_buf; + } + file = zend_string_init(abspath, strlen(abspath), 0); phpdbg_list_file(file, param->file.line, 0, 0); - efree(file); + zend_string_release(file); } break; phpdbg_default_switch_case(); @@ -110,10 +117,10 @@ PHPDBG_LIST(class) /* {{{ */ if (ce->info.user.filename) { phpdbg_list_file(ce->info.user.filename, ce->info.user.line_end - ce->info.user.line_start + 1, ce->info.user.line_start, 0); } else { - phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ce->name); + phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ZSTR_VAL(ce->name)); } } else { - phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ce->name); + phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ZSTR_VAL(ce->name)); } } else { phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "The requested class (%s) could not be found", param->str); @@ -126,16 +133,8 @@ void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highli { uint line, lastline; phpdbg_file_source *data; - char resolved_path_buf[MAXPATHLEN]; - const char *abspath; - if (VCWD_REALPATH(filename->val, resolved_path_buf)) { - abspath = resolved_path_buf; - } else { - abspath = filename->val; - } - - if (!(data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), abspath, strlen(abspath)))) { + if (!(data = zend_hash_find_ptr(&PHPDBG_G(file_sources), filename))) { phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file..."); return; } @@ -151,7 +150,7 @@ void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highli lastline = data->lines; } - phpdbg_xml("<list %r file=\"%s\">", filename); + phpdbg_xml("<list %r file=\"%s\">", ZSTR_VAL(filename)); for (line = offset; line < lastline;) { uint linestart = data->line[line++]; @@ -181,7 +180,7 @@ void phpdbg_list_function(const zend_function *fbc) /* {{{ */ const zend_op_array *ops; if (fbc->type != ZEND_USER_FUNCTION) { - phpdbg_error("list", "type=\"internalfunction\" function=\"%s\"", "The function requested (%s) is not user defined", fbc->common.function_name); + phpdbg_error("list", "type=\"internalfunction\" function=\"%s\"", "The function requested (%s) is not user defined", ZSTR_VAL(fbc->common.function_name)); return; } @@ -231,43 +230,37 @@ void phpdbg_list_function_byname(const char *str, size_t len) /* {{{ */ efree(func_name); } /* }}} */ +/* 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 */ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { phpdbg_file_source data, *dataptr; - zend_file_handle fake = {{0}}; + zend_file_handle fake; zend_op_array *ret; - char *filename = (char *)(file->opened_path ? file->opened_path->val : file->filename); + char *filename; uint line; char *bufptr, *endptr; - char resolved_path_buf[MAXPATHLEN]; - - zend_stream_fixup(file, &data.buf, &data.len); - - data.filename = filename; - data.line[0] = 0; - if (file->handle.stream.mmap.old_closer) { - /* do not unmap */ - file->handle.stream.closer = file->handle.stream.mmap.old_closer; + if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) { + return PHPDBG_G(compile_file)(file, type); } -#if HAVE_MMAP - if (file->handle.stream.mmap.map) { - data.map = file->handle.stream.mmap.map; + filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + + data.buf = emalloc(data.len + ZEND_MMAP_AHEAD + 1); + if (data.len > 0) { + memcpy(data.buf, bufptr, data.len); } -#endif + memset(data.buf + data.len, 0, ZEND_MMAP_AHEAD + 1); + data.line[0] = 0; + memset(&fake, 0, sizeof(fake)); fake.type = ZEND_HANDLE_MAPPED; fake.handle.stream.mmap.buf = data.buf; fake.handle.stream.mmap.len = data.len; fake.free_filename = 0; - fake.opened_path = file->opened_path; fake.filename = filename; fake.opened_path = file->opened_path; *(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data; - if (VCWD_REALPATH(filename, resolved_path_buf)) { - filename = resolved_path_buf; - } for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) { if (*bufptr == '\n') { @@ -276,34 +269,134 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { } dataptr->lines = ++line; dataptr->line[line] = endptr - data.buf; - dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); - - zend_hash_str_add_ptr(&PHPDBG_G(file_sources), filename, strlen(filename), dataptr); - phpdbg_resolve_pending_file_break(filename); ret = PHPDBG_G(compile_file)(&fake, type); + if (ret == NULL) { + efree(data.buf); + efree(dataptr); + + fake.opened_path = NULL; + zend_file_handle_dtor(&fake); + + return NULL; + } + + dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + zend_hash_add_ptr(&PHPDBG_G(file_sources), ret->filename, dataptr); + phpdbg_resolve_pending_file_break(ZSTR_VAL(ret->filename)); + fake.opened_path = NULL; zend_file_handle_dtor(&fake); return ret; } -void phpdbg_free_file_source(phpdbg_file_source *data) { -#if HAVE_MMAP - if (data->map) { - munmap(data->map, data->len + ZEND_MMAP_AHEAD); - } else -#endif +zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) { + char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + char resolved_path_buf[MAXPATHLEN]; + zend_op_array *op_array; + phpdbg_file_source *dataptr; + + if (VCWD_REALPATH(filename, resolved_path_buf)) { + filename = resolved_path_buf; + + if (file->opened_path) { + zend_string_release(file->opened_path); + file->opened_path = zend_string_init(filename, strlen(filename), 0); + } else { + if (file->free_filename) { + efree((char *) file->filename); + } + file->free_filename = 0; + file->filename = filename; + } + } + + op_array = PHPDBG_G(init_compile_file)(file, type); + + if (op_array == NULL) { + return NULL; + } + + dataptr = zend_hash_find_ptr(&PHPDBG_G(file_sources), op_array->filename); + ZEND_ASSERT(dataptr != NULL); + + dataptr->op_array = *op_array; + if (dataptr->op_array.refcount) { + ++*dataptr->op_array.refcount; + } + + return op_array; +} + +zend_op_array *phpdbg_compile_string(zval *source_string, char *filename) { + zend_string *fake_name; + zend_op_array *op_array; + phpdbg_file_source *dataptr; + uint line; + char *bufptr, *endptr; + + if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) { + return PHPDBG_G(compile_string)(source_string, filename); + } + + dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * Z_STRLEN_P(source_string)); + dataptr->buf = estrndup(Z_STRVAL_P(source_string), Z_STRLEN_P(source_string)); + dataptr->len = Z_STRLEN_P(source_string); + dataptr->line[0] = 0; + for (line = 0, bufptr = dataptr->buf - 1, endptr = dataptr->buf + dataptr->len; ++bufptr < endptr;) { + if (*bufptr == '\n') { + dataptr->line[++line] = (uint)(bufptr - dataptr->buf) + 1; + } + } + dataptr->lines = ++line; + dataptr->line[line] = endptr - dataptr->buf; + + op_array = PHPDBG_G(compile_string)(source_string, filename); + + if (op_array == NULL) { + efree(dataptr->buf); + efree(dataptr); + return NULL; + } + + fake_name = strpprintf(0, "%s%c%p", filename, 0, op_array->opcodes); + + dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + zend_hash_add_ptr(&PHPDBG_G(file_sources), fake_name, dataptr); + + zend_string_release(fake_name); + + dataptr->op_array = *op_array; + if (dataptr->op_array.refcount) { + ++*dataptr->op_array.refcount; + } + + return op_array; +} + +void phpdbg_free_file_source(zval *zv) { + phpdbg_file_source *data = Z_PTR_P(zv); + if (data->buf) { efree(data->buf); } + destroy_op_array(&data->op_array); + efree(data); } void phpdbg_init_list(void) { PHPDBG_G(compile_file) = zend_compile_file; + PHPDBG_G(compile_string) = zend_compile_string; zend_hash_init(&PHPDBG_G(file_sources), 1, NULL, (dtor_func_t) phpdbg_free_file_source, 0); zend_compile_file = phpdbg_compile_file; + zend_compile_string = phpdbg_compile_string; +} + +void phpdbg_list_update(void) { + PHPDBG_G(init_compile_file) = zend_compile_file; + zend_compile_file = phpdbg_init_compile_file; } |