]> granicus.if.org Git - php/commitdiff
Clear FG(user_stream_current_filename) when bailing out
authorSara Golemon <pollita@php.net>
Wed, 12 Oct 2016 04:14:25 +0000 (21:14 -0700)
committerSara Golemon <pollita@php.net>
Wed, 12 Oct 2016 04:55:01 +0000 (21:55 -0700)
If a userwrapper opener E_ERRORs then FG(user_stream_current_filename)
would remain set until the next request and would not be pointing
at unallocated memory.

Catch the bailout, clear the variable, then continue bailing.

Closes https://bugs.php.net/bug.php?id=73188

NEWS
ext/standard/tests/streams/user-stream-error.phpt [new file with mode: 0644]
main/streams/userspace.c

diff --git a/NEWS b/NEWS
index cf765ff3dc3a293ca8459ba5aad3ffa23ded83fa..d9e6b4c1d356034aa679233b04feec4daadd166d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ PHP                                                                        NEWS
 
 - Standard:
   . Fixed bug #73203 (passing additional_parameters causes mail to fail). (cmb)
+  . Fixed bug #73188 (use after free in userspace streams). (Sara)
 
 13 Oct 2016, PHP 5.6.27
 
diff --git a/ext/standard/tests/streams/user-stream-error.phpt b/ext/standard/tests/streams/user-stream-error.phpt
new file mode 100644 (file)
index 0000000..e7351b4
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+E_ERROR during UserStream Open
+--FILE--
+<?php
+
+class FailStream {
+  public function stream_open($path, $mode, $options, &$opened_path) {
+    _some_undefined_function();
+  }
+}
+stream_wrapper_register('mystream', 'FailStream');
+fopen('mystream://foo', 'r');
+echo 'Done';
+
+--EXPECTF--
+Fatal error: Call to undefined function _some_undefined_function() in %s/user-stream-error.php on line %d
index e65f605b12631a5fc97184931d5dfa7c3800d6a3..37c0a176ed7d66e0c3e9f2e90e2b6885f23ee30a 100644 (file)
@@ -394,12 +394,17 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *
        MAKE_STD_ZVAL(zfuncname);
        ZVAL_STRING(zfuncname, USERSTREAM_OPEN, 1);
 
-       call_result = call_user_function_ex(NULL,
-                       &us->object,
-                       zfuncname,
-                       &zretval,
-                       4, args,
-                       0, NULL TSRMLS_CC);
+       zend_try {
+               call_result = call_user_function_ex(NULL,
+                               &us->object,
+                               zfuncname,
+                               &zretval,
+                               4, args,
+                               0, NULL TSRMLS_CC);
+       } zend_catch {
+               FG(user_stream_current_filename) = NULL;
+               zend_bailout();
+       } zend_end_try();
 
        if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
                /* the stream is now open! */