summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2020-12-23 01:38:40 +0100
committerThomas Deutschmann <whissi@gentoo.org>2020-12-23 01:39:05 +0100
commit280c5e27b96f27eed2f3325576d74361abb36294 (patch)
treee1f1136a4da39b4ca0c04b134666eda45780e9c8
parentdev-lang/spidermonkey: Stabilize 78.6.0 ppc64, #761205 (diff)
downloadgentoo-280c5e27b96f27eed2f3325576d74361abb36294.tar.gz
gentoo-280c5e27b96f27eed2f3325576d74361abb36294.tar.bz2
gentoo-280c5e27b96f27eed2f3325576d74361abb36294.zip
dev-lang/php: fix use-after-free when accessing already destructed backtrace arguments
Bug: https://bugs.gentoo.org/711140 Package-Manager: Portage-3.0.12, Repoman-3.0.2 Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
-rw-r--r--dev-lang/php/files/php-7.2.34-use-after-free-bug76047.patch174
-rw-r--r--dev-lang/php/php-7.2.34-r1.ebuild (renamed from dev-lang/php/php-7.2.34.ebuild)1
2 files changed, 175 insertions, 0 deletions
diff --git a/dev-lang/php/files/php-7.2.34-use-after-free-bug76047.patch b/dev-lang/php/files/php-7.2.34-use-after-free-bug76047.patch
new file mode 100644
index 000000000000..b3a864ee82a8
--- /dev/null
+++ b/dev-lang/php/files/php-7.2.34-use-after-free-bug76047.patch
@@ -0,0 +1,174 @@
+Backport of https://git.php.net/?p=php-src.git;a=commit;h=ef1e4891b47949c8dc0f9482eef9454a0ecdfa1d
+
+--- a/Zend/tests/bug52361.phpt
++++ b/Zend/tests/bug52361.phpt
+@@ -25,9 +25,8 @@ try {
+ --EXPECTF--
+ 1. Exception: aaa in %sbug52361.php:5
+ Stack trace:
+-#0 %sbug52361.php(13): aaa->__destruct()
+-#1 %sbug52361.php(16): bbb()
+-#2 {main}
++#0 %sbug52361.php(16): aaa->__destruct()
++#1 {main}
+ 2. Exception: bbb in %sbug52361.php:13
+ Stack trace:
+ #0 %sbug52361.php(16): bbb()
+--- /dev/null
++++ b/Zend/tests/bug76047.phpt
+@@ -0,0 +1,68 @@
++--TEST--
++Bug #76047: Use-after-free when accessing already destructed backtrace arguments
++--FILE--
++<?php
++
++class Vuln {
++ public $a;
++ public function __destruct() {
++ unset($this->a);
++ $backtrace = (new Exception)->getTrace();
++ var_dump($backtrace);
++ }
++}
++
++function test($arg) {
++ $arg = str_shuffle(str_repeat('A', 79));
++ $vuln = new Vuln();
++ $vuln->a = $arg;
++}
++
++function test2($arg) {
++ $$arg = 1; // Trigger symbol table
++ $arg = str_shuffle(str_repeat('A', 79));
++ $vuln = new Vuln();
++ $vuln->a = $arg;
++}
++
++test('x');
++test2('x');
++
++?>
++--EXPECTF--
++array(1) {
++ [0]=>
++ array(6) {
++ ["file"]=>
++ string(%d) "%s"
++ ["line"]=>
++ int(%d)
++ ["function"]=>
++ string(10) "__destruct"
++ ["class"]=>
++ string(4) "Vuln"
++ ["type"]=>
++ string(2) "->"
++ ["args"]=>
++ array(0) {
++ }
++ }
++}
++array(1) {
++ [0]=>
++ array(6) {
++ ["file"]=>
++ string(%d) "%s"
++ ["line"]=>
++ int(%d)
++ ["function"]=>
++ string(10) "__destruct"
++ ["class"]=>
++ string(4) "Vuln"
++ ["type"]=>
++ string(2) "->"
++ ["args"]=>
++ array(0) {
++ }
++ }
++}
+--- a/Zend/zend_vm_def.h
++++ b/Zend/zend_vm_def.h
+@@ -2366,9 +2366,9 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
+ uint32_t call_info = EX_CALL_INFO();
+
+ if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+
+- EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
+ zend_object *object = Z_OBJ(execute_data->This);
+ #if 0
+@@ -2394,12 +2394,12 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
+ LOAD_NEXT_OPLINE();
+ ZEND_VM_LEAVE();
+ } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table));
+ }
+- EG(current_execute_data) = EX(prev_execute_data);
+
+ /* Free extra args before releasing the closure,
+ * as that may free the op_array. */
+@@ -2449,6 +2449,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
+ ZEND_VM_LEAVE();
+ } else {
+ if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+ if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) {
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+@@ -2456,7 +2457,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
+ }
+ zend_vm_stack_free_extra_args_ex(call_info, execute_data);
+ }
+- EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
+ }
+--- a/Zend/zend_vm_execute.h
++++ b/Zend/zend_vm_execute.h
+@@ -434,9 +434,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
+ uint32_t call_info = EX_CALL_INFO();
+
+ if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+
+- EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
+ zend_object *object = Z_OBJ(execute_data->This);
+ #if 0
+@@ -462,12 +462,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
+ LOAD_NEXT_OPLINE();
+ ZEND_VM_LEAVE();
+ } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table));
+ }
+- EG(current_execute_data) = EX(prev_execute_data);
+
+ /* Free extra args before releasing the closure,
+ * as that may free the op_array. */
+@@ -517,6 +517,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
+ ZEND_VM_LEAVE();
+ } else {
+ if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
++ EG(current_execute_data) = EX(prev_execute_data);
+ i_free_compiled_variables(execute_data);
+ if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) {
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+@@ -524,7 +525,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
+ }
+ zend_vm_stack_free_extra_args_ex(call_info, execute_data);
+ }
+- EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
+ }
+
diff --git a/dev-lang/php/php-7.2.34.ebuild b/dev-lang/php/php-7.2.34-r1.ebuild
index b7fe1520efba..a534bc594e5f 100644
--- a/dev-lang/php/php-7.2.34.ebuild
+++ b/dev-lang/php/php-7.2.34-r1.ebuild
@@ -157,6 +157,7 @@ RESTRICT="!test? ( test )"
PATCHES=(
"${FILESDIR}/php-freetype-2.9.1.patch"
"${FILESDIR}/php-7.2.13-intl-use-icu-namespace.patch"
+ "${FILESDIR}/php-7.2.34-use-after-free-bug76047.patch"
)
PHP_MV="$(ver_cut 1)"