Skip to content

Commit 73e070a

Browse files
committed
Refactor user streams to use ZPP class check
Closes GH-5876
1 parent 2a72778 commit 73e070a

File tree

2 files changed

+43
-44
lines changed

2 files changed

+43
-44
lines changed

ext/standard/tests/file/userstreams.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,11 @@ class mystream
156156

157157
}
158158

159-
if (@stream_wrapper_register("bogus", "class_not_exist")) {
159+
try {
160+
stream_wrapper_register("bogus", "class_not_exist");
160161
die("Registered a non-existent class!!!???");
162+
} catch (\TypeError $e) {
163+
echo $e->getMessage() . \PHP_EOL;
161164
}
162165
echo "Not Registered\n";
163166

@@ -315,6 +318,7 @@ echo $data . "\n";
315318

316319
?>
317320
--EXPECT--
321+
stream_wrapper_register(): Argument #2 ($classname) must be a valid class name, class_not_exist given
318322
Not Registered
319323
Registered
320324
Registered

main/streams/userspace.c

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ static int le_protocols;
3636

3737
struct php_user_stream_wrapper {
3838
char * protoname;
39-
char * classname;
4039
zend_class_entry *ce;
4140
php_stream_wrapper wrapper;
4241
};
@@ -71,7 +70,6 @@ static void stream_wrapper_dtor(zend_resource *rsrc)
7170
struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr;
7271

7372
efree(uwrap->protoname);
74-
efree(uwrap->classname);
7573
efree(uwrap);
7674
}
7775

@@ -375,7 +373,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *
375373
ZVAL_COPY(&stream->wrapperdata, &us->object);
376374
} else {
377375
php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_OPEN "\" call failed",
378-
us->wrapper->classname);
376+
ZSTR_VAL(us->wrapper->ce->name));
379377
}
380378

381379
/* destroy everything else */
@@ -444,7 +442,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
444442
ZVAL_COPY(&stream->wrapperdata, &us->object);
445443
} else {
446444
php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed",
447-
us->wrapper->classname);
445+
ZSTR_VAL(us->wrapper->ce->name));
448446
}
449447

450448
/* destroy everything else */
@@ -468,38 +466,35 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
468466
/* {{{ Registers a custom URL protocol handler class */
469467
PHP_FUNCTION(stream_wrapper_register)
470468
{
471-
zend_string *protocol, *classname;
472-
struct php_user_stream_wrapper * uwrap;
469+
zend_string *protocol;
470+
struct php_user_stream_wrapper *uwrap;
471+
zend_class_entry *ce = NULL;
473472
zend_resource *rsrc;
474473
zend_long flags = 0;
475474

476-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &protocol, &classname, &flags) == FAILURE) {
475+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "SC|l", &protocol, &ce, &flags) == FAILURE) {
477476
RETURN_THROWS();
478477
}
479478

480479
uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
480+
uwrap->ce = ce;
481481
uwrap->protoname = estrndup(ZSTR_VAL(protocol), ZSTR_LEN(protocol));
482-
uwrap->classname = estrndup(ZSTR_VAL(classname), ZSTR_LEN(classname));
483482
uwrap->wrapper.wops = &user_stream_wops;
484483
uwrap->wrapper.abstract = uwrap;
485484
uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);
486485

487486
rsrc = zend_register_resource(uwrap, le_protocols);
488487

489-
if ((uwrap->ce = zend_lookup_class(classname)) != NULL) {
490-
if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
491-
RETURN_TRUE;
492-
} else {
493-
/* We failed. But why? */
494-
if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
495-
php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
496-
} else {
497-
/* Hash doesn't exist so it must have been an invalid protocol scheme */
498-
php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(classname), ZSTR_VAL(protocol));
499-
}
500-
}
488+
if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
489+
RETURN_TRUE;
490+
}
491+
492+
/* We failed. But why? */
493+
if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
494+
php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
501495
} else {
502-
php_error_docref(NULL, E_WARNING, "Class '%s' is undefined", ZSTR_VAL(classname));
496+
/* Hash doesn't exist so it must have been an invalid protocol scheme */
497+
php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(uwrap->ce->name), ZSTR_VAL(protocol));
503498
}
504499

505500
zend_list_delete(rsrc);
@@ -596,14 +591,14 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_
596591
}
597592
} else {
598593
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
599-
us->wrapper->classname);
594+
ZSTR_VAL(us->wrapper->ce->name));
600595
didwrite = -1;
601596
}
602597

603598
/* don't allow strange buffer overruns due to bogus return */
604599
if (didwrite > 0 && didwrite > count) {
605600
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " wrote " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " written, " ZEND_LONG_FMT " max)",
606-
us->wrapper->classname,
601+
ZSTR_VAL(us->wrapper->ce->name),
607602
(zend_long)(didwrite - count), (zend_long)didwrite, (zend_long)count);
608603
didwrite = count;
609604
}
@@ -643,7 +638,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
643638

644639
if (call_result == FAILURE) {
645640
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!",
646-
us->wrapper->classname);
641+
ZSTR_VAL(us->wrapper->ce->name));
647642
return -1;
648643
}
649644

@@ -659,7 +654,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
659654
if (didread > 0) {
660655
if (didread > count) {
661656
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " - read " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " read, " ZEND_LONG_FMT " max) - excess data will be lost",
662-
us->wrapper->classname, (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
657+
ZSTR_VAL(us->wrapper->ce->name), (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
663658
didread = count;
664659
}
665660
memcpy(buf, Z_STRVAL(retval), didread);
@@ -688,7 +683,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
688683
} else if (call_result == FAILURE) {
689684
php_error_docref(NULL, E_WARNING,
690685
"%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
691-
us->wrapper->classname);
686+
ZSTR_VAL(us->wrapper->ce->name));
692687

693688
stream->eof = 1;
694689
}
@@ -812,7 +807,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when
812807
*newoffs = Z_LVAL(retval);
813808
ret = 0;
814809
} else if (call_result == FAILURE) {
815-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", us->wrapper->classname);
810+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", ZSTR_VAL(us->wrapper->ce->name));
816811
ret = -1;
817812
} else {
818813
ret = -1;
@@ -884,7 +879,7 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb)
884879
} else {
885880
if (call_result == FAILURE) {
886881
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!",
887-
us->wrapper->classname);
882+
ZSTR_VAL(us->wrapper->ce->name));
888883
}
889884
}
890885

@@ -913,7 +908,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
913908
ret = PHP_STREAM_OPTION_RETURN_ERR;
914909
php_error_docref(NULL, E_WARNING,
915910
"%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
916-
us->wrapper->classname);
911+
ZSTR_VAL(us->wrapper->ce->name));
917912
}
918913
zval_ptr_dtor(&retval);
919914
zval_ptr_dtor(&func_name);
@@ -954,7 +949,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
954949
ret = PHP_STREAM_OPTION_RETURN_OK;
955950
} else {
956951
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
957-
us->wrapper->classname);
952+
ZSTR_VAL(us->wrapper->ce->name));
958953
ret = PHP_STREAM_OPTION_RETURN_ERR;
959954
}
960955
}
@@ -993,12 +988,12 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
993988
} else {
994989
php_error_docref(NULL, E_WARNING,
995990
"%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
996-
us->wrapper->classname);
991+
ZSTR_VAL(us->wrapper->ce->name));
997992
}
998993
} else {
999994
php_error_docref(NULL, E_WARNING,
1000995
"%s::" USERSTREAM_TRUNCATE " is not implemented!",
1001-
us->wrapper->classname);
996+
ZSTR_VAL(us->wrapper->ce->name));
1002997
}
1003998
zval_ptr_dtor(&retval);
1004999
zval_ptr_dtor(&args[0]);
@@ -1053,7 +1048,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
10531048

10541049
if (call_result == FAILURE) {
10551050
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
1056-
us->wrapper->classname);
1051+
ZSTR_VAL(us->wrapper->ce->name));
10571052
ret = PHP_STREAM_OPTION_RETURN_ERR;
10581053
} else if (zend_is_true(&retval)) {
10591054
ret = PHP_STREAM_OPTION_RETURN_OK;
@@ -1104,7 +1099,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int
11041099
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
11051100
ret = (Z_TYPE(zretval) == IS_TRUE);
11061101
} else if (call_result == FAILURE) {
1107-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", uwrap->classname);
1102+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name));
11081103
}
11091104

11101105
/* clean up */
@@ -1148,7 +1143,7 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from
11481143
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
11491144
ret = (Z_TYPE(zretval) == IS_TRUE);
11501145
} else if (call_result == FAILURE) {
1151-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", uwrap->classname);
1146+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name));
11521147
}
11531148

11541149
/* clean up */
@@ -1194,7 +1189,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int
11941189
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
11951190
ret = (Z_TYPE(zretval) == IS_TRUE);
11961191
} else if (call_result == FAILURE) {
1197-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname);
1192+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
11981193
}
11991194

12001195
/* clean up */
@@ -1240,7 +1235,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url,
12401235
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
12411236
ret = (Z_TYPE(zretval) == IS_TRUE);
12421237
} else if (call_result == FAILURE) {
1243-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname);
1238+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
12441239
}
12451240

12461241
/* clean up */
@@ -1310,7 +1305,7 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i
13101305
if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
13111306
ret = Z_TYPE(zretval) == IS_TRUE;
13121307
} else if (call_result == FAILURE) {
1313-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", uwrap->classname);
1308+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name));
13141309
}
13151310

13161311
/* clean up */
@@ -1361,7 +1356,7 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i
13611356
} else {
13621357
if (call_result == FAILURE) {
13631358
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!",
1364-
uwrap->classname);
1359+
ZSTR_VAL(uwrap->ce->name));
13651360
}
13661361
}
13671362

@@ -1405,7 +1400,7 @@ static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t co
14051400
didread = sizeof(php_stream_dirent);
14061401
} else if (call_result == FAILURE) {
14071402
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!",
1408-
us->wrapper->classname);
1403+
ZSTR_VAL(us->wrapper->ce->name));
14091404
}
14101405

14111406
zval_ptr_dtor(&retval);
@@ -1491,7 +1486,7 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
14911486
do {
14921487
if (call_result == FAILURE) {
14931488
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
1494-
us->wrapper->classname);
1489+
ZSTR_VAL(us->wrapper->ce->name));
14951490
break;
14961491
}
14971492
if (!zend_is_true(&retval)) {
@@ -1500,12 +1495,12 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
15001495
php_stream_from_zval_no_verify(intstream, &retval);
15011496
if (!intstream) {
15021497
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
1503-
us->wrapper->classname);
1498+
ZSTR_VAL(us->wrapper->ce->name));
15041499
break;
15051500
}
15061501
if (intstream == stream) {
15071502
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
1508-
us->wrapper->classname);
1503+
ZSTR_VAL(us->wrapper->ce->name));
15091504
intstream = NULL;
15101505
break;
15111506
}

0 commit comments

Comments
 (0)