]> granicus.if.org Git - php/commitdiff
Refactor user streams to use ZPP class check
authorGeorge Peter Banyard <girgias@php.net>
Mon, 20 Jul 2020 12:47:35 +0000 (13:47 +0100)
committerGeorge Peter Banyard <girgias@php.net>
Tue, 28 Jul 2020 16:12:40 +0000 (17:12 +0100)
Closes GH-5876

ext/standard/tests/file/userstreams.phpt
main/streams/userspace.c

index 5b753e02e4f346e3ca042ee31cab651996f02dbb..101604f5abcecefc6352b9662bb43847af3a6280 100644 (file)
@@ -156,8 +156,11 @@ class mystream
 
 }
 
-if (@stream_wrapper_register("bogus", "class_not_exist")) {
+try {
+    stream_wrapper_register("bogus", "class_not_exist");
     die("Registered a non-existent class!!!???");
+} catch (\TypeError $e) {
+    echo $e->getMessage() . \PHP_EOL;
 }
 echo "Not Registered\n";
 
@@ -315,6 +318,7 @@ echo $data . "\n";
 
 ?>
 --EXPECT--
+stream_wrapper_register(): Argument #2 ($classname) must be a valid class name, class_not_exist given
 Not Registered
 Registered
 Registered
index d9fc112aa1e5ee85c16e061d1df8a35fb586bcff..f6381a0014c4935596b293b526976fee8671787a 100644 (file)
@@ -36,7 +36,6 @@ static int le_protocols;
 
 struct php_user_stream_wrapper {
        char * protoname;
-       char * classname;
        zend_class_entry *ce;
        php_stream_wrapper wrapper;
 };
@@ -71,7 +70,6 @@ static void stream_wrapper_dtor(zend_resource *rsrc)
        struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr;
 
        efree(uwrap->protoname);
-       efree(uwrap->classname);
        efree(uwrap);
 }
 
@@ -375,7 +373,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *
                ZVAL_COPY(&stream->wrapperdata, &us->object);
        } else {
                php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_OPEN "\" call failed",
-                       us->wrapper->classname);
+                       ZSTR_VAL(us->wrapper->ce->name));
        }
 
        /* destroy everything else */
@@ -444,7 +442,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
                ZVAL_COPY(&stream->wrapperdata, &us->object);
        } else {
                php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed",
-                       us->wrapper->classname);
+                       ZSTR_VAL(us->wrapper->ce->name));
        }
 
        /* destroy everything else */
@@ -468,38 +466,35 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char
 /* {{{ Registers a custom URL protocol handler class */
 PHP_FUNCTION(stream_wrapper_register)
 {
-       zend_string *protocol, *classname;
-       struct php_user_stream_wrapper * uwrap;
+       zend_string *protocol;
+       struct php_user_stream_wrapper *uwrap;
+       zend_class_entry *ce = NULL;
        zend_resource *rsrc;
        zend_long flags = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &protocol, &classname, &flags) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "SC|l", &protocol, &ce, &flags) == FAILURE) {
                RETURN_THROWS();
        }
 
        uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
+       uwrap->ce = ce;
        uwrap->protoname = estrndup(ZSTR_VAL(protocol), ZSTR_LEN(protocol));
-       uwrap->classname = estrndup(ZSTR_VAL(classname), ZSTR_LEN(classname));
        uwrap->wrapper.wops = &user_stream_wops;
        uwrap->wrapper.abstract = uwrap;
        uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);
 
        rsrc = zend_register_resource(uwrap, le_protocols);
 
-       if ((uwrap->ce = zend_lookup_class(classname)) != NULL) {
-               if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
-                       RETURN_TRUE;
-               } else {
-                       /* We failed.  But why? */
-                       if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
-                               php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
-                       } else {
-                               /* Hash doesn't exist so it must have been an invalid protocol scheme */
-                               php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(classname), ZSTR_VAL(protocol));
-                       }
-               }
+       if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
+               RETURN_TRUE;
+       }
+
+       /* We failed.  But why? */
+       if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
+               php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
        } else {
-               php_error_docref(NULL, E_WARNING, "Class '%s' is undefined", ZSTR_VAL(classname));
+               /* Hash doesn't exist so it must have been an invalid protocol scheme */
+               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));
        }
 
        zend_list_delete(rsrc);
@@ -596,14 +591,14 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_
                }
        } else {
                php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
-                               us->wrapper->classname);
+                               ZSTR_VAL(us->wrapper->ce->name));
                didwrite = -1;
        }
 
        /* don't allow strange buffer overruns due to bogus return */
        if (didwrite > 0 && didwrite > count) {
                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)",
-                               us->wrapper->classname,
+                               ZSTR_VAL(us->wrapper->ce->name),
                                (zend_long)(didwrite - count), (zend_long)didwrite, (zend_long)count);
                didwrite = count;
        }
@@ -643,7 +638,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
 
        if (call_result == FAILURE) {
                php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!",
-                               us->wrapper->classname);
+                               ZSTR_VAL(us->wrapper->ce->name));
                return -1;
        }
 
@@ -659,7 +654,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
        if (didread > 0) {
                if (didread > count) {
                        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",
-                                       us->wrapper->classname, (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
+                                       ZSTR_VAL(us->wrapper->ce->name), (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
                        didread = count;
                }
                memcpy(buf, Z_STRVAL(retval), didread);
@@ -688,7 +683,7 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count
        } else if (call_result == FAILURE) {
                php_error_docref(NULL, E_WARNING,
                                "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
-                               us->wrapper->classname);
+                               ZSTR_VAL(us->wrapper->ce->name));
 
                stream->eof = 1;
        }
@@ -812,7 +807,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when
                *newoffs = Z_LVAL(retval);
                ret = 0;
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", us->wrapper->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", ZSTR_VAL(us->wrapper->ce->name));
                ret = -1;
        } else {
                ret = -1;
@@ -884,7 +879,7 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb)
        } else {
                if (call_result == FAILURE) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                }
        }
 
@@ -913,7 +908,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
                        ret = PHP_STREAM_OPTION_RETURN_ERR;
                        php_error_docref(NULL, E_WARNING,
                                        "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                }
                zval_ptr_dtor(&retval);
                zval_ptr_dtor(&func_name);
@@ -954,7 +949,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
                                ret = PHP_STREAM_OPTION_RETURN_OK;
                        } else {
                                php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
-                                                                us->wrapper->classname);
+                                                                ZSTR_VAL(us->wrapper->ce->name));
                                ret = PHP_STREAM_OPTION_RETURN_ERR;
                        }
                }
@@ -993,12 +988,12 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
                                        } else {
                                                php_error_docref(NULL, E_WARNING,
                                                                "%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
-                                                               us->wrapper->classname);
+                                                               ZSTR_VAL(us->wrapper->ce->name));
                                        }
                                } else {
                                        php_error_docref(NULL, E_WARNING,
                                                        "%s::" USERSTREAM_TRUNCATE " is not implemented!",
-                                                       us->wrapper->classname);
+                                                       ZSTR_VAL(us->wrapper->ce->name));
                                }
                                zval_ptr_dtor(&retval);
                                zval_ptr_dtor(&args[0]);
@@ -1053,7 +1048,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
 
                if (call_result == FAILURE) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                        ret = PHP_STREAM_OPTION_RETURN_ERR;
                } else if (zend_is_true(&retval)) {
                        ret = PHP_STREAM_OPTION_RETURN_OK;
@@ -1104,7 +1099,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int
        if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
                ret = (Z_TYPE(zretval) == IS_TRUE);
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", uwrap->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name));
        }
 
        /* clean up */
@@ -1148,7 +1143,7 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from
        if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
                ret = (Z_TYPE(zretval) == IS_TRUE);
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", uwrap->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name));
        }
 
        /* clean up */
@@ -1194,7 +1189,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int
        if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
                ret = (Z_TYPE(zretval) == IS_TRUE);
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
        }
 
        /* clean up */
@@ -1240,7 +1235,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url,
        if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
                ret = (Z_TYPE(zretval) == IS_TRUE);
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
        }
 
        /* clean up */
@@ -1310,7 +1305,7 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i
        if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
                ret = Z_TYPE(zretval) == IS_TRUE;
        } else if (call_result == FAILURE) {
-               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", uwrap->classname);
+               php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name));
        }
 
        /* clean up */
@@ -1361,7 +1356,7 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i
        } else {
                if (call_result == FAILURE) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!",
-                                       uwrap->classname);
+                                       ZSTR_VAL(uwrap->ce->name));
                }
        }
 
@@ -1405,7 +1400,7 @@ static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t co
                didread = sizeof(php_stream_dirent);
        } else if (call_result == FAILURE) {
                php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!",
-                               us->wrapper->classname);
+                               ZSTR_VAL(us->wrapper->ce->name));
        }
 
        zval_ptr_dtor(&retval);
@@ -1491,7 +1486,7 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
        do {
                if (call_result == FAILURE) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                        break;
                }
                if (!zend_is_true(&retval)) {
@@ -1500,12 +1495,12 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
                php_stream_from_zval_no_verify(intstream, &retval);
                if (!intstream) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                        break;
                }
                if (intstream == stream) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
-                                       us->wrapper->classname);
+                                       ZSTR_VAL(us->wrapper->ce->name));
                        intstream = NULL;
                        break;
                }