Skip to content

Commit 4db70fd

Browse files
committed
fix bug #40459 - make all stream funcs that create object call ctor
1 parent 01e414b commit 4db70fd

File tree

2 files changed

+183
-117
lines changed

2 files changed

+183
-117
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
--TEST--
2+
bug 40459 - Test whether the constructor of the user-space stream wrapper is called when stream functions are called
3+
--FILE--
4+
<?php
5+
// Test whether the constructor of the user-space stream wrapper is called when stream functions are called
6+
class testwrapper {
7+
private $constructorCalled = false;
8+
function __construct() {
9+
$this->constructorCalled = true;
10+
}
11+
12+
function stream_open($path, $mode, $options, &$opened_path)
13+
{
14+
echo $this->constructorCalled ? 'yes' : 'no';
15+
return true;
16+
}
17+
18+
function url_stat($url, $flags)
19+
{
20+
echo $this->constructorCalled ? 'yes' : 'no';
21+
return array();
22+
}
23+
24+
function unlink($url)
25+
{
26+
echo $this->constructorCalled ? 'yes' : 'no';
27+
}
28+
29+
function rename($from, $to)
30+
{
31+
echo $this->constructorCalled ? 'yes' : 'no';
32+
}
33+
34+
function mkdir($dir, $mode, $options)
35+
{
36+
echo $this->constructorCalled ? 'yes' : 'no';
37+
}
38+
39+
function rmdir($dir, $options)
40+
{
41+
echo $this->constructorCalled ? 'yes' : 'no';
42+
}
43+
44+
function dir_opendir($url, $options)
45+
{
46+
echo $this->constructorCalled ? 'yes' : 'no';
47+
return TRUE;
48+
}
49+
function stream_metadata()
50+
{
51+
echo $this->constructorCalled ? 'yes' : 'no';
52+
return TRUE;
53+
}
54+
}
55+
56+
stream_wrapper_register('test', 'testwrapper', STREAM_IS_URL);
57+
58+
echo 'stream_open: ';
59+
fopen('test://test', 'r');
60+
echo "\n";
61+
62+
echo 'url_stat: ';
63+
stat('test://test');
64+
echo "\n";
65+
66+
echo 'dir_opendir: ';
67+
opendir('test://test');
68+
echo "\n";
69+
70+
echo 'rmdir: ';
71+
rmdir('test://test');
72+
echo "\n";
73+
74+
echo 'mkdir: ';
75+
mkdir('test://test');
76+
echo "\n";
77+
78+
echo 'rename: ';
79+
rename('test://test', 'test://test2');
80+
echo "\n";
81+
82+
echo 'unlink: ';
83+
unlink('test://test');
84+
echo "\n";
85+
86+
echo 'touch: ';
87+
touch('test://test', time());
88+
echo "\n";
89+
90+
91+
92+
?>
93+
==DONE==
94+
--EXPECT--
95+
stream_open: yes
96+
url_stat: yes
97+
dir_opendir: yes
98+
rmdir: yes
99+
mkdir: yes
100+
rename: yes
101+
unlink: yes
102+
touch: yes
103+
==DONE==

main/streams/userspace.c

Lines changed: 80 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -281,43 +281,22 @@ typedef struct _php_userstream_data php_userstream_data_t;
281281
282282
}}} **/
283283

284-
static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
284+
static zval *user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context TSRMLS_DC)
285285
{
286-
struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
287-
php_userstream_data_t *us;
288-
zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
289-
zval **args[4];
290-
int call_result;
291-
php_stream *stream = NULL;
292-
zend_bool old_in_user_include;
293-
294-
/* Try to catch bad usage without preventing flexibility */
295-
if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
296-
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
297-
return NULL;
298-
}
299-
FG(user_stream_current_filename) = filename;
286+
zval *object;
287+
/* create an instance of our class */
288+
ALLOC_ZVAL(object);
289+
object_init_ex(object, uwrap->ce);
290+
Z_SET_REFCOUNT_P(object, 1);
291+
Z_SET_ISREF_P(object);
300292

301-
/* if the user stream was registered as local and we are in include context,
302-
we add allow_url_include restrictions to allow_url_fopen ones */
303-
/* we need only is_url == 0 here since if is_url == 1 and remote wrappers
304-
were restricted we wouldn't get here */
305-
old_in_user_include = PG(in_user_include);
306-
if(uwrap->wrapper.is_url == 0 &&
307-
(options & STREAM_OPEN_FOR_INCLUDE) &&
308-
!PG(allow_url_include)) {
309-
PG(in_user_include) = 1;
293+
if (context) {
294+
add_property_resource(object, "context", context->rsrc_id);
295+
zend_list_addref(context->rsrc_id);
296+
} else {
297+
add_property_null(object, "context");
310298
}
311299

312-
us = emalloc(sizeof(*us));
313-
us->wrapper = uwrap;
314-
315-
/* create an instance of our class */
316-
ALLOC_ZVAL(us->object);
317-
object_init_ex(us->object, uwrap->ce);
318-
Z_SET_REFCOUNT_P(us->object, 1);
319-
Z_SET_ISREF_P(us->object);
320-
321300
if (uwrap->ce->constructor) {
322301
zend_fcall_info fci;
323302
zend_fcall_info_cache fcc;
@@ -327,7 +306,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
327306
fci.function_table = &uwrap->ce->function_table;
328307
fci.function_name = NULL;
329308
fci.symbol_table = NULL;
330-
fci.object_ptr = us->object;
309+
fci.object_ptr = object;
331310
fci.retval_ptr_ptr = &retval_ptr;
332311
fci.param_count = 0;
333312
fci.params = NULL;
@@ -336,29 +315,60 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
336315
fcc.initialized = 1;
337316
fcc.function_handler = uwrap->ce->constructor;
338317
fcc.calling_scope = EG(scope);
339-
fcc.called_scope = Z_OBJCE_P(us->object);
340-
fcc.object_ptr = us->object;
318+
fcc.called_scope = Z_OBJCE_P(object);
319+
fcc.object_ptr = object;
341320

342321
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
343322
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute %s::%s()", uwrap->ce->name, uwrap->ce->constructor->common.function_name);
344-
zval_dtor(us->object);
345-
FREE_ZVAL(us->object);
346-
efree(us);
347-
FG(user_stream_current_filename) = NULL;
348-
PG(in_user_include) = old_in_user_include;
323+
zval_dtor(object);
324+
FREE_ZVAL(object);
349325
return NULL;
350326
} else {
351327
if (retval_ptr) {
352328
zval_ptr_dtor(&retval_ptr);
353329
}
354330
}
355331
}
332+
return object;
333+
}
356334

357-
if (context) {
358-
add_property_resource(us->object, "context", context->rsrc_id);
359-
zend_list_addref(context->rsrc_id);
360-
} else {
361-
add_property_null(us->object, "context");
335+
static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
336+
{
337+
struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
338+
php_userstream_data_t *us;
339+
zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
340+
zval **args[4];
341+
int call_result;
342+
php_stream *stream = NULL;
343+
zend_bool old_in_user_include;
344+
345+
/* Try to catch bad usage without preventing flexibility */
346+
if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
347+
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
348+
return NULL;
349+
}
350+
FG(user_stream_current_filename) = filename;
351+
352+
/* if the user stream was registered as local and we are in include context,
353+
we add allow_url_include restrictions to allow_url_fopen ones */
354+
/* we need only is_url == 0 here since if is_url == 1 and remote wrappers
355+
were restricted we wouldn't get here */
356+
old_in_user_include = PG(in_user_include);
357+
if(uwrap->wrapper.is_url == 0 &&
358+
(options & STREAM_OPEN_FOR_INCLUDE) &&
359+
!PG(allow_url_include)) {
360+
PG(in_user_include) = 1;
361+
}
362+
363+
us = emalloc(sizeof(*us));
364+
us->wrapper = uwrap;
365+
366+
us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
367+
if(us->object == NULL) {
368+
FG(user_stream_current_filename) = NULL;
369+
PG(in_user_include) = old_in_user_include;
370+
efree(us);
371+
return NULL;
362372
}
363373

364374
/* call it's stream_open method - set up params first */
@@ -447,17 +457,11 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
447457
us = emalloc(sizeof(*us));
448458
us->wrapper = uwrap;
449459

450-
/* create an instance of our class */
451-
ALLOC_ZVAL(us->object);
452-
object_init_ex(us->object, uwrap->ce);
453-
Z_SET_REFCOUNT_P(us->object, 1);
454-
Z_SET_ISREF_P(us->object);
455-
456-
if (context) {
457-
add_property_resource(us->object, "context", context->rsrc_id);
458-
zend_list_addref(context->rsrc_id);
459-
} else {
460-
add_property_null(us->object, "context");
460+
us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
461+
if(us == NULL) {
462+
FG(user_stream_current_filename) = NULL;
463+
efree(us);
464+
return NULL;
461465
}
462466

463467
/* call it's dir_open method - set up params first */
@@ -1157,16 +1161,9 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
11571161
int ret = 0;
11581162

11591163
/* create an instance of our class */
1160-
ALLOC_ZVAL(object);
1161-
object_init_ex(object, uwrap->ce);
1162-
Z_SET_REFCOUNT_P(object, 1);
1163-
Z_SET_ISREF_P(object);
1164-
1165-
if (context) {
1166-
add_property_resource(object, "context", context->rsrc_id);
1167-
zend_list_addref(context->rsrc_id);
1168-
} else {
1169-
add_property_null(object, "context");
1164+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1165+
if(object == NULL) {
1166+
return ret;
11701167
}
11711168

11721169
/* call the unlink method */
@@ -1211,16 +1208,9 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
12111208
int ret = 0;
12121209

12131210
/* create an instance of our class */
1214-
ALLOC_ZVAL(object);
1215-
object_init_ex(object, uwrap->ce);
1216-
Z_SET_REFCOUNT_P(object, 1);
1217-
Z_SET_ISREF_P(object);
1218-
1219-
if (context) {
1220-
add_property_resource(object, "context", context->rsrc_id);
1221-
zend_list_addref(context->rsrc_id);
1222-
} else {
1223-
add_property_null(object, "context");
1211+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1212+
if(object == NULL) {
1213+
return ret;
12241214
}
12251215

12261216
/* call the rename method */
@@ -1270,16 +1260,9 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode,
12701260
int ret = 0;
12711261

12721262
/* create an instance of our class */
1273-
ALLOC_ZVAL(object);
1274-
object_init_ex(object, uwrap->ce);
1275-
Z_SET_REFCOUNT_P(object, 1);
1276-
Z_SET_ISREF_P(object);
1277-
1278-
if (context) {
1279-
add_property_resource(object, "context", context->rsrc_id);
1280-
zend_list_addref(context->rsrc_id);
1281-
} else {
1282-
add_property_null(object, "context");
1263+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1264+
if(object == NULL) {
1265+
return ret;
12831266
}
12841267

12851268
/* call the mkdir method */
@@ -1335,16 +1318,9 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
13351318
int ret = 0;
13361319

13371320
/* create an instance of our class */
1338-
ALLOC_ZVAL(object);
1339-
object_init_ex(object, uwrap->ce);
1340-
Z_SET_REFCOUNT_P(object, 1);
1341-
Z_SET_ISREF_P(object);
1342-
1343-
if (context) {
1344-
add_property_resource(object, "context", context->rsrc_id);
1345-
zend_list_addref(context->rsrc_id);
1346-
} else {
1347-
add_property_null(object, "context");
1321+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1322+
if(object == NULL) {
1323+
return ret;
13481324
}
13491325

13501326
/* call the rmdir method */
@@ -1420,16 +1396,10 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, char *url, int opt
14201396
}
14211397

14221398
/* create an instance of our class */
1423-
ALLOC_ZVAL(object);
1424-
object_init_ex(object, uwrap->ce);
1425-
Z_SET_REFCOUNT_P(object, 1);
1426-
Z_SET_ISREF_P(object);
1427-
1428-
if (context) {
1429-
add_property_resource(object, "context", context->rsrc_id);
1430-
zend_list_addref(context->rsrc_id);
1431-
} else {
1432-
add_property_null(object, "context");
1399+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1400+
if(object == NULL) {
1401+
zval_ptr_dtor(&zvalue);
1402+
return ret;
14331403
}
14341404

14351405
/* call the mkdir method */
@@ -1484,16 +1454,9 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int fla
14841454
int ret = -1;
14851455

14861456
/* create an instance of our class */
1487-
ALLOC_ZVAL(object);
1488-
object_init_ex(object, uwrap->ce);
1489-
Z_SET_REFCOUNT_P(object, 1);
1490-
Z_SET_ISREF_P(object);
1491-
1492-
if (context) {
1493-
add_property_resource(object, "context", context->rsrc_id);
1494-
zend_list_addref(context->rsrc_id);
1495-
} else {
1496-
add_property_null(object, "context");
1457+
object = user_stream_create_object(uwrap, context TSRMLS_CC);
1458+
if(object == NULL) {
1459+
return ret;
14971460
}
14981461

14991462
/* call it's stat_url method - set up params first */

0 commit comments

Comments
 (0)