]> granicus.if.org Git - php/commitdiff
Fixed bug #79793
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 14:24:13 +0000 (16:24 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 7 Jul 2020 14:29:48 +0000 (16:29 +0200)
Make sure the string key is not released while throwing the
undefined index warning.

NEWS
Zend/tests/bug79793.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/NEWS b/NEWS
index bfe7b596ebfc9347263e048144c357e476e0131b..6c35059e5e5bcbb1f130513cf2a583d673f704ef 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,8 @@ PHP                                                                        NEWS
     (Nikita)
   . Fixed bug #79784 (Use after free if changing array during undef var during
     array write fetch). (Nikita)
+  . Fixed bug #79793 (Use after free if string used in undefined index warning
+    is changed). (Nikita)
 
 - Fileinfo:
   . Fixed bug #79756 (finfo_file crash (FILEINFO_MIME)). (cmb)
diff --git a/Zend/tests/bug79793.phpt b/Zend/tests/bug79793.phpt
new file mode 100644 (file)
index 0000000..9e4e2e2
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #79793: Use after free if string used in undefined index warning is changed
+--FILE--
+<?php
+
+$key = "foo";
+$key .= "bar";
+set_error_handler(function($_, $m) use (&$key) {
+    echo "$m\n";
+    $key .= "baz";
+});
+
+$ary = [];
+$ary[$key]++;
+var_dump($ary);
+$ary[$key] += 1;
+var_dump($ary);
+
+?>
+--EXPECT--
+Undefined index: foobar
+array(1) {
+  ["foobar"]=>
+  int(1)
+}
+Undefined index: foobarbaz
+array(2) {
+  ["foobar"]=>
+  int(1)
+  ["foobarbaz"]=>
+  int(1)
+}
index 5aed92ff45250e3d0f6af93d3e833120b0389042..59c151fe66ed0a565ecc5fb0e33b7306fabc2c6a 100644 (file)
@@ -2181,10 +2181,15 @@ str_index:
                                        retval = &EG(uninitialized_zval);
                                        break;
                                case BP_VAR_RW:
+                                       /* Key may be released while throwing the undefined index warning. */
+                                       zend_string_addref(offset_key);
                                        if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
+                                               zend_string_release(offset_key);
                                                return NULL;
                                        }
-                                       /* break missing intentionally */
+                                       retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
+                                       zend_string_release(offset_key);
+                                       break;
                                case BP_VAR_W:
                                        retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
                                        break;