[php-src] master: Add dedicated StreamBucket class (#13111)
| From: | Máté Kocsis via GitHub | Date: | Thu, 11 Apr 2024 18:11:47 +0000 |
| Subject: | [php-src] master: Add dedicated StreamBucket class (#13111) | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-128077@lists.php.net to get a copy of this message | ||
Author: Máté Kocsis (kocsismate)
Committer: GitHub (web-flow)
Pusher: kocsismate
Date: 2024-04-11T20:11:40+02:00
Commit: https://github.com/php/php-src/commit/be2f454d6ebcaf6f58c41544f21f53a5109b1e5d
Raw diff: https://github.com/php/php-src/commit/be2f454d6ebcaf6f58c41544f21f53a5109b1e5d.diff
Add dedicated StreamBucket class (#13111)
RFC: https://wiki.php.net/rfc/dedicated_stream_bucket
Changed paths:
M ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt
M ext/standard/basic_functions.stub.php
M ext/standard/basic_functions_arginfo.h
M ext/standard/tests/file/bug39551.phpt
M ext/standard/user_filters.c
M ext/standard/user_filters.stub.php
M ext/standard/user_filters_arginfo.h
Diff:
diff --git a/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt
b/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt
index 5c4d1cb87f1d7..5a230936fff96 100644
--- a/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt
+++ b/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt
@@ -8,7 +8,7 @@ $standard = new ReflectionExtension('standard');
var_dump($standard->getClassNames());
?>
--EXPECT--
-array(4) {
+array(5) {
[0]=>
string(22) "__PHP_Incomplete_Class"
[1]=>
@@ -16,5 +16,7 @@ array(4) {
[2]=>
string(15) "php_user_filter"
[3]=>
+ string(12) "StreamBucket"
+ [4]=>
string(9) "Directory"
}
diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php
index c3adaceff4390..dabb9fc1434a5 100644
--- a/ext/standard/basic_functions.stub.php
+++ b/ext/standard/basic_functions.stub.php
@@ -3744,19 +3744,19 @@ function get_headers(string $url, bool $associative = false, $context =
null): a
* @param resource $brigade
* @refcount 1
*/
-function stream_bucket_make_writeable($brigade): ?object {}
+function stream_bucket_make_writeable($brigade): ?StreamBucket {}
/** @param resource $brigade */
-function stream_bucket_prepend($brigade, object $bucket): void {}
+function stream_bucket_prepend($brigade, StreamBucket $bucket): void {}
/** @param resource $brigade */
-function stream_bucket_append($brigade, object $bucket): void {}
+function stream_bucket_append($brigade, StreamBucket $bucket): void {}
/**
* @param resource $stream
* @refcount 1
*/
-function stream_bucket_new($stream, string $buffer): object {}
+function stream_bucket_new($stream, string $buffer): StreamBucket {}
/**
* @return array<int, string>
diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h
index c420e5c29e0f7..4556e10ada82b 100644
--- a/ext/standard/basic_functions_arginfo.h
+++ b/ext/standard/basic_functions_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 954bf48ac1f24a14fd7508c8bf4b781883398499 */
+ * Stub hash: 1ef54fdebc6a206c4af3438130db0cd12a62c8b6 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@@ -2104,18 +2104,18 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_headers, 0, 1,
MAY_BE_ARRAY|
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, context, "null")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_stream_bucket_make_writeable, 0, 1, IS_OBJECT, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_stream_bucket_make_writeable, 0, 1, StreamBucket, 1)
ZEND_ARG_INFO(0, brigade)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_stream_bucket_prepend, 0, 2, IS_VOID, 0)
ZEND_ARG_INFO(0, brigade)
- ZEND_ARG_TYPE_INFO(0, bucket, IS_OBJECT, 0)
+ ZEND_ARG_OBJ_INFO(0, bucket, StreamBucket, 0)
ZEND_END_ARG_INFO()
#define arginfo_stream_bucket_append arginfo_stream_bucket_prepend
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_stream_bucket_new, 0, 2, IS_OBJECT, 0)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_stream_bucket_new, 0, 2, StreamBucket, 0)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_TYPE_INFO(0, buffer, IS_STRING, 0)
ZEND_END_ARG_INFO()
diff --git a/ext/standard/tests/file/bug39551.phpt b/ext/standard/tests/file/bug39551.phpt
index e6982fcaab10a..5b0674342dea5 100644
--- a/ext/standard/tests/file/bug39551.phpt
+++ b/ext/standard/tests/file/bug39551.phpt
@@ -4,6 +4,7 @@ Bug #39551 (Segfault with stream_bucket_new in user filter)
<?php
$bucket = stream_bucket_new(fopen('php://temp', 'w+'), '');
+var_dump($bucket);
class bucketFilter extends php_user_filter {
public function filter($in, $out, &$consumed, $closing ): int {
@@ -20,5 +21,15 @@ stream_get_contents($s);
echo "Done\n";
?>
---EXPECT--
+--EXPECTF--
+object(StreamBucket)#%d (%d) {
+ ["bucket"]=>
+ resource(%d) of type (userfilter.bucket)
+ ["data"]=>
+ string(0) ""
+ ["datalen"]=>
+ int(0)
+ ["dataLength"]=>
+ int(0)
+}
Done
diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c
index 9cdd1b26b7de6..f4ffae9559276 100644
--- a/ext/standard/user_filters.c
+++ b/ext/standard/user_filters.c
@@ -61,6 +61,7 @@ PHP_METHOD(php_user_filter, onClose)
}
static zend_class_entry *user_filter_class_entry;
+static zend_class_entry *stream_bucket_class_entry;
static ZEND_RSRC_DTOR_FUNC(php_bucket_dtor)
{
@@ -75,6 +76,7 @@ PHP_MINIT_FUNCTION(user_filters)
{
/* init the filter class ancestor */
user_filter_class_entry = register_class_php_user_filter();
+ stream_bucket_class_entry = register_class_StreamBucket();
/* Filters will dispose of their brigades */
le_bucket_brigade = zend_register_list_destructors_ex(NULL, NULL, PHP_STREAM_BRIGADE_RES_NAME,
module_number);
@@ -351,16 +353,17 @@ PHP_FUNCTION(stream_bucket_make_writeable)
RETURN_THROWS();
}
- ZVAL_NULL(return_value);
-
if (brigade->head && (bucket = php_stream_bucket_make_writeable(brigade->head))) {
ZVAL_RES(&zbucket, zend_register_resource(bucket, le_bucket));
- object_init(return_value);
- add_property_zval(return_value, "bucket", &zbucket);
+ object_init_ex(return_value, stream_bucket_class_entry);
+ zend_update_property(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("bucket"), &zbucket);
/* add_property_zval increments the refcount which is unwanted here */
zval_ptr_dtor(&zbucket);
- add_property_stringl(return_value, "data", bucket->buf, bucket->buflen);
- add_property_long(return_value, "datalen", bucket->buflen);
+ zend_update_property_stringl(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("data"), bucket->buf, bucket->buflen);
+ zend_update_property_long(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("datalen"), bucket->buflen);
+ zend_update_property_long(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("dataLength"), bucket->buflen);
+ } else {
+ ZVAL_NULL(return_value);
}
}
/* }}} */
@@ -369,30 +372,32 @@ PHP_FUNCTION(stream_bucket_make_writeable)
static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
{
zval *zbrigade, *zobject;
- zval *pzbucket, *pzdata;
+ zval *pzbucket, *pzdata, rv;
php_stream_bucket_brigade *brigade;
php_stream_bucket *bucket;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_RESOURCE(zbrigade)
- Z_PARAM_OBJECT(zobject)
+ Z_PARAM_OBJECT_OF_CLASS(zobject, stream_bucket_class_entry)
ZEND_PARSE_PARAMETERS_END();
- if (NULL == (pzbucket = zend_hash_str_find_deref(Z_OBJPROP_P(zobject), "bucket",
sizeof("bucket")-1))) {
- zend_argument_value_error(2, "must be an object that has a \"bucket\"
property");
+ if ((brigade = (php_stream_bucket_brigade*)zend_fetch_resource(
+ Z_RES_P(zbrigade), PHP_STREAM_BRIGADE_RES_NAME, le_bucket_brigade)) == NULL) {
RETURN_THROWS();
}
- if ((brigade = (php_stream_bucket_brigade*)zend_fetch_resource(
- Z_RES_P(zbrigade), PHP_STREAM_BRIGADE_RES_NAME, le_bucket_brigade)) == NULL) {
+ if (NULL == (pzbucket = zend_read_property(NULL, Z_OBJ_P(zobject), "bucket",
sizeof("bucket")-1, false, &rv))) {
+ zend_argument_value_error(2, "must be an object that has a \"bucket\"
property");
RETURN_THROWS();
}
+ ZVAL_DEREF(pzbucket);
if ((bucket = (php_stream_bucket *)zend_fetch_resource_ex(pzbucket, PHP_STREAM_BUCKET_RES_NAME,
le_bucket)) == NULL) {
RETURN_THROWS();
}
- if (NULL != (pzdata = zend_hash_str_find_deref(Z_OBJPROP_P(zobject), "data",
sizeof("data")-1)) && Z_TYPE_P(pzdata) == IS_STRING) {
+ if (NULL != (pzdata = zend_read_property(NULL, Z_OBJ_P(zobject), "data",
sizeof("data")-1, false, &rv))) {
+ ZVAL_DEREF(pzdata);
if (!bucket->own_buf) {
bucket = php_stream_bucket_make_writeable(bucket);
}
@@ -454,12 +459,13 @@ PHP_FUNCTION(stream_bucket_new)
bucket = php_stream_bucket_new(stream, pbuffer, buffer_len, 1, php_stream_is_persistent(stream));
ZVAL_RES(&zbucket, zend_register_resource(bucket, le_bucket));
- object_init(return_value);
- add_property_zval(return_value, "bucket", &zbucket);
+ object_init_ex(return_value, stream_bucket_class_entry);
+ zend_update_property(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("bucket"), &zbucket);
/* add_property_zval increments the refcount which is unwanted here */
zval_ptr_dtor(&zbucket);
- add_property_stringl(return_value, "data", bucket->buf, bucket->buflen);
- add_property_long(return_value, "datalen", bucket->buflen);
+ zend_update_property_stringl(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("data"), bucket->buf, bucket->buflen);
+ zend_update_property_long(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("datalen"), bucket->buflen);
+ zend_update_property_long(Z_OBJCE_P(return_value), Z_OBJ_P(return_value),
ZEND_STRL("dataLength"), bucket->buflen);
}
/* }}} */
diff --git a/ext/standard/user_filters.stub.php b/ext/standard/user_filters.stub.php
index 3c134ea1bb5b9..acaa42bb33c84 100644
--- a/ext/standard/user_filters.stub.php
+++ b/ext/standard/user_filters.stub.php
@@ -55,3 +55,18 @@ public function onCreate(): bool {}
/** @tentative-return-type */
public function onClose(): void {}
}
+
+final class StreamBucket
+{
+ /**
+ * @var resource
+ * @readonly
+ */
+ public $bucket;
+ /** @readonly */
+ public string $data;
+ /** @readonly */
+ public int $datalen;
+ /** @readonly */
+ public int $dataLength;
+}
diff --git a/ext/standard/user_filters_arginfo.h b/ext/standard/user_filters_arginfo.h
index 53c535b4eb9af..a40a00f7ee476 100644
--- a/ext/standard/user_filters_arginfo.h
+++ b/ext/standard/user_filters_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 1c03251b4e0b22056da43bf86087d6996454d2a0 */
+ * Stub hash: 33264435fe01a2cc9aa21a4a087dbbf3c4007206 */
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_php_user_filter_filter, 0, 4,
IS_LONG, 0)
ZEND_ARG_INFO(0, in)
@@ -25,6 +25,10 @@ static const zend_function_entry class_php_user_filter_methods[] = {
ZEND_FE_END
};
+static const zend_function_entry class_StreamBucket_methods[] = {
+ ZEND_FE_END
+};
+
static void register_user_filters_symbols(int module_number)
{
REGISTER_LONG_CONSTANT("PSFS_PASS_ON", PSFS_PASS_ON, CONST_PERSISTENT);
@@ -62,3 +66,38 @@ static zend_class_entry *register_class_php_user_filter(void)
return class_entry;
}
+
+static zend_class_entry *register_class_StreamBucket(void)
+{
+ zend_class_entry ce, *class_entry;
+
+ INIT_CLASS_ENTRY(ce, "StreamBucket", class_StreamBucket_methods);
+ class_entry = zend_register_internal_class_ex(&ce, NULL);
+ class_entry->ce_flags |= ZEND_ACC_FINAL;
+
+ zval property_bucket_default_value;
+ ZVAL_NULL(&property_bucket_default_value);
+ zend_string *property_bucket_name = zend_string_init("bucket",
sizeof("bucket") - 1, 1);
+ zend_declare_typed_property(class_entry, property_bucket_name, &property_bucket_default_value,
ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0));
+ zend_string_release(property_bucket_name);
+
+ zval property_data_default_value;
+ ZVAL_UNDEF(&property_data_default_value);
+ zend_string *property_data_name = zend_string_init("data", sizeof("data") - 1,
1);
+ zend_declare_typed_property(class_entry, property_data_name, &property_data_default_value,
ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
+ zend_string_release(property_data_name);
+
+ zval property_datalen_default_value;
+ ZVAL_UNDEF(&property_datalen_default_value);
+ zend_string *property_datalen_name = zend_string_init("datalen",
sizeof("datalen") - 1, 1);
+ zend_declare_typed_property(class_entry, property_datalen_name,
&property_datalen_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type)
ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+ zend_string_release(property_datalen_name);
+
+ zval property_dataLength_default_value;
+ ZVAL_UNDEF(&property_dataLength_default_value);
+ zend_string *property_dataLength_name = zend_string_init("dataLength",
sizeof("dataLength") - 1, 1);
+ zend_declare_typed_property(class_entry, property_dataLength_name,
&property_dataLength_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type)
ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+ zend_string_release(property_dataLength_name);
+
+ return class_entry;
+}