[php-src] master: stream: improve bugfix, check class is instantiable prior to registering (#22806)

Gina Peter Banyard via GitHub <[email protected]> Sun, 19 Jul 2026 16:15:35 +0000
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Gina Peter Banyard (Girgias)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2026-07-19T17:15:32+01:00

Commit: https://github.com/php/php-src/commit/e10141588ac5446851386a04a96d638cf0a0e681
Raw diff: https://github.com/php/php-src/commit/e10141588ac5446851386a04a96d638cf0a0e681.diff

stream: improve bugfix, check class is instantiable prior to registering (#22806)

Rather than when attempting to create an instance of it within the stream layer.

Changed paths:
  M  ext/standard/tests/streams/bug74951.phpt
  M  main/streams/userspace.c


Diff:

diff --git a/ext/standard/tests/streams/bug74951.phpt b/ext/standard/tests/streams/bug74951.phpt
index b30b5fe2824e..2668f541fb3c 100644
--- a/ext/standard/tests/streams/bug74951.phpt
+++ b/ext/standard/tests/streams/bug74951.phpt
@@ -6,8 +6,12 @@ trait Stream00ploiter{
   public function s() {}
   public function n($_) {}
 }
-stream_wrapper_register('e0ploit','Stream00ploiter');
-$s=fopen('e0ploit://',0);
+
+try {
+	stream_wrapper_register('e0ploit','Stream00ploiter');
+} catch (\Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
+}
 ?>
---EXPECTF--
-Warning: fopen(): Failed to open stream: operation failed in %s%ebug74951.php on line 7
+--EXPECT--
+ValueError: stream_wrapper_register(): Argument #2 ($class) must be a concrete class
diff --git a/main/streams/userspace.c b/main/streams/userspace.c
index bf6ffa500963..9b6f283c075d 100644
--- a/main/streams/userspace.c
+++ b/main/streams/userspace.c
@@ -249,10 +249,7 @@ typedef struct _php_userstream_data php_userstream_data_t;
 
 static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object)
 {
-	if (uwrap->ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
-		ZVAL_UNDEF(object);
-		return;
-	}
+	ZEND_ASSERT((uwrap->ce->ce_flags & ZEND_ACC_UNINSTANTIABLE) == 0);
 
 	/* create an instance of our class */
 	if (object_init_ex(object, uwrap->ce) == FAILURE) {
@@ -467,6 +464,11 @@ PHP_FUNCTION(stream_wrapper_register)
 		RETURN_THROWS();
 	}
 
+	if (UNEXPECTED(ce->ce_flags & ZEND_ACC_UNINSTANTIABLE)) {
+		zend_argument_value_error(2, "must be a concrete class");
+		RETURN_THROWS();
+	}
+
 	uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
 	uwrap->ce = ce;
 	uwrap->wrapper.wops = &user_stream_wops;