Skip to content

Commit 7e12b5d

Browse files
committed
Fixed issue getting executable lines from custom wrappers
See also krakjoe/phpdbg#161
1 parent fee5c04 commit 7e12b5d

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ PHP NEWS
1818
- Phpdbg:
1919
. Fixed bug #73615 (phpdbg without option never load .phpdbginit at startup).
2020
(Bob)
21+
. Fixed issue getting executable lines from custom wrappers. (Bob)
2122

2223
08 Dec 2016 PHP 7.0.14
2324

sapi/phpdbg/phpdbg_list.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,16 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
235235
phpdbg_file_source data, *dataptr;
236236
zend_file_handle fake;
237237
zend_op_array *ret;
238-
char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
238+
char *filename;
239239
uint line;
240240
char *bufptr, *endptr;
241-
char resolved_path_buf[MAXPATHLEN];
242241

243242
if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) {
244243
return PHPDBG_G(compile_file)(file, type);
245244
}
246245

246+
filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
247+
247248
data.buf = emalloc(data.len + ZEND_MMAP_AHEAD + 1);
248249
if (data.len > 0) {
249250
memcpy(data.buf, bufptr, data.len);
@@ -261,9 +262,6 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
261262
fake.opened_path = file->opened_path;
262263

263264
*(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data;
264-
if (VCWD_REALPATH(filename, resolved_path_buf)) {
265-
filename = resolved_path_buf;
266-
}
267265

268266
for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) {
269267
if (*bufptr == '\n') {
@@ -323,6 +321,8 @@ zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) {
323321
return NULL;
324322
}
325323

324+
filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename);
325+
326326
dataptr = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), filename, strlen(filename));
327327
ZEND_ASSERT(dataptr != NULL);
328328

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
function foo()
4+
{
5+
return '<result>'; // line 5 is executable
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
--TEST--
2+
Getting executable lines from custom wrappers
3+
--PHPDBG--
4+
r
5+
q
6+
--EXPECTF--
7+
[Successful compilation of %s]
8+
prompt> array(1) {
9+
[5]=>
10+
int(0)
11+
}
12+
[Script ended normally]
13+
prompt>
14+
--FILE--
15+
<?php
16+
17+
/**
18+
* This example demonstrates how phpdbg_get_executable() behaves differently
19+
* when passed the 'files' option vs without, in the face of some mild abuse
20+
* of stream wrappers.
21+
*/
22+
23+
/**
24+
* First, we define a stream wrapper that simply maps to a real file on disk.
25+
*/
26+
final class StreamWrapper
27+
{
28+
public function stream_open(
29+
string $path,
30+
string $mode,
31+
int $options = 0,
32+
string &$openedPath = null
33+
) : bool {
34+
if ($mode[0] !== 'r') {
35+
return false;
36+
}
37+
38+
list($scheme, $path) = explode('://', $path, 2);
39+
40+
$stream = \fopen($path, $mode);
41+
42+
if ($stream === false) {
43+
return false;
44+
}
45+
46+
$this->stream = $stream;
47+
48+
/**
49+
* The $openedPath reference variable is assigned, indicating the
50+
* *actual* path that was opened. This affects the behaviour of
51+
* constants like __FILE__.
52+
*/
53+
$openedPath = \realpath($path);
54+
55+
return true;
56+
}
57+
58+
public function stream_read(int $count) : string { return \fread($this->stream, $count); }
59+
public function stream_close() : bool { return \fclose($this->stream); }
60+
public function stream_eof() : bool { return \feof($this->stream); }
61+
public function stream_stat() { return \fstat($this->stream); }
62+
63+
private $stream = false;
64+
}
65+
66+
stream_wrapper_register('wrapper', StreamWrapper::class);
67+
68+
/**
69+
* Next, we include a PHP file that contains executable lines, via the stream
70+
* wrapper.
71+
*/
72+
$filename = __DIR__ . '/phpdbg_get_executable_stream_wrapper.inc';
73+
require 'wrapper://' . $filename;
74+
75+
/**
76+
* If we call phpdbg_get_executable() and pass no options, the realpath of the
77+
* included file is present in the array, but indicates no executable lines.
78+
*/
79+
$x = phpdbg_get_executable();
80+
81+
// We expect [5 => 0], but got an empty array ...
82+
var_dump($x[$filename]);
83+
84+
?>

0 commit comments

Comments
 (0)