Refactor user streams to use ZPP class check

Closes GH-5876
This commit is contained in:
George Peter Banyard 2020-07-20 13:47:35 +01:00
parent 2a72778e2d
commit 73e070a614
2 changed files with 43 additions and 44 deletions

View 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

View 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;
}