From 7e12b5da712f603d4ff68c378c0b1f06dcc495db Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 6 Dec 2016 18:27:31 +0100 Subject: [PATCH] Fixed issue getting executable lines from custom wrappers See also krakjoe/phpdbg#161 --- NEWS | 1 + sapi/phpdbg/phpdbg_list.c | 10 +-- .../phpdbg_get_executable_stream_wrapper.inc | 6 ++ .../phpdbg_get_executable_stream_wrapper.phpt | 84 +++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.inc create mode 100644 sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt diff --git a/NEWS b/NEWS index 901d9f5e077..0222f56c7a1 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ PHP NEWS - Phpdbg: . Fixed bug #73615 (phpdbg without option never load .phpdbginit at startup). (Bob) + . Fixed issue getting executable lines from custom wrappers. (Bob) 08 Dec 2016 PHP 7.0.14 diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index b0bb157f085..1b70039fda2 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -235,15 +235,16 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { phpdbg_file_source data, *dataptr; zend_file_handle fake; zend_op_array *ret; - char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + char *filename; uint line; char *bufptr, *endptr; - char resolved_path_buf[MAXPATHLEN]; if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) { return PHPDBG_G(compile_file)(file, type); } + 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); @@ -261,9 +262,6 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { 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') { @@ -323,6 +321,8 @@ zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) { return NULL; } + filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + dataptr = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), filename, strlen(filename)); ZEND_ASSERT(dataptr != NULL); diff --git a/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.inc b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.inc new file mode 100644 index 00000000000..4f4155715d9 --- /dev/null +++ b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.inc @@ -0,0 +1,6 @@ +'; // line 5 is executable +} diff --git a/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt new file mode 100644 index 00000000000..0ddbd6f527a --- /dev/null +++ b/sapi/phpdbg/tests/phpdbg_get_executable_stream_wrapper.phpt @@ -0,0 +1,84 @@ +--TEST-- +Getting executable lines from custom wrappers +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> array(1) { + [5]=> + int(0) +} +[Script ended normally] +prompt> +--FILE-- +stream = $stream; + + /** + * The $openedPath reference variable is assigned, indicating the + * *actual* path that was opened. This affects the behaviour of + * constants like __FILE__. + */ + $openedPath = \realpath($path); + + return true; + } + + public function stream_read(int $count) : string { return \fread($this->stream, $count); } + public function stream_close() : bool { return \fclose($this->stream); } + public function stream_eof() : bool { return \feof($this->stream); } + public function stream_stat() { return \fstat($this->stream); } + + private $stream = false; +} + +stream_wrapper_register('wrapper', StreamWrapper::class); + +/** + * Next, we include a PHP file that contains executable lines, via the stream + * wrapper. + */ +$filename = __DIR__ . '/phpdbg_get_executable_stream_wrapper.inc'; +require 'wrapper://' . $filename; + +/** + * If we call phpdbg_get_executable() and pass no options, the realpath of the + * included file is present in the array, but indicates no executable lines. + */ +$x = phpdbg_get_executable(); + +// We expect [5 => 0], but got an empty array ... +var_dump($x[$filename]); + +?>