summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-31 10:29:26 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-31 10:29:45 +0100
commitd422478f6d10691b63a8bc64072e929fd457bfe9 (patch)
tree3bde7527af020f1af3565e7252d9df9605296b7b
parentdb7193f31ea9d176214fc36cde0503864a75ab0d (diff)
parentef1e4891b47949c8dc0f9482eef9454a0ecdfa1d (diff)
downloadphp-git-d422478f6d10691b63a8bc64072e929fd457bfe9.tar.gz
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fix bug #76047
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug52361.phpt5
-rw-r--r--Zend/tests/bug76047.phpt68
-rw-r--r--Zend/tests/bug78973.phpt1
-rw-r--r--Zend/zend_vm_def.h6
-rw-r--r--Zend/zend_vm_execute.h12
6 files changed, 81 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index a4ef1ef469..bc617738de 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ PHP NEWS
. Fixed bug #78989 (Delayed variance check involving trait segfaults).
(Nikita)
. Fixed bug #79174 (cookie values with spaces fail to round-trip). (cmb)
+ . Fixed bug #76047 (Use-after-free when accessing already destructed
+ backtrace arguments). (Nikita)
- CURL:
. Fixed bug #79078 (Hypothetical use-after-free in curl_multi_add_handle()).
diff --git a/Zend/tests/bug52361.phpt b/Zend/tests/bug52361.phpt
index 74ed8a8d17..5ffe569e4a 100644
--- 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()
diff --git a/Zend/tests/bug76047.phpt b/Zend/tests/bug76047.phpt
new file mode 100644
index 0000000000..f0f743ee3d
--- /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) {
+ }
+ }
+}
diff --git a/Zend/tests/bug78973.phpt b/Zend/tests/bug78973.phpt
index e1286e0a85..688f4e6cc5 100644
--- a/Zend/tests/bug78973.phpt
+++ b/Zend/tests/bug78973.phpt
@@ -16,4 +16,3 @@ test(new class {
?>
--EXPECTF--
#0 class@anonymous->__destruct() called at [%s:%d]
-#1 test() called at [%s:%d]
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 1499b4b5ef..f33d07b738 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2876,12 +2876,12 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
SAVE_OPLINE();
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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
#endif
- EG(current_execute_data) = EX(prev_execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
OBJ_RELEASE(Z_OBJ(execute_data->This));
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -2898,6 +2898,7 @@ ZEND_VM_HOT_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);
#ifdef ZEND_PREFER_RELOAD
@@ -2906,7 +2907,6 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
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. */
@@ -2950,6 +2950,7 @@ ZEND_VM_HOT_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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
@@ -2960,7 +2961,6 @@ ZEND_VM_HOT_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_CLOSURE_OBJECT(EX(func)));
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1e5f6455e3..3987d1b945 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1133,12 +1133,12 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
SAVE_OPLINE();
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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
#endif
- EG(current_execute_data) = EX(prev_execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
OBJ_RELEASE(Z_OBJ(execute_data->This));
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -1155,6 +1155,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
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);
#ifdef ZEND_PREFER_RELOAD
@@ -1163,7 +1164,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
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. */
@@ -1207,6 +1207,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
@@ -1217,7 +1218,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
}
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_CLOSURE_OBJECT(EX(func)));
}
@@ -53675,12 +53675,12 @@ zend_leave_helper_SPEC_LABEL:
SAVE_OPLINE();
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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
#endif
- EG(current_execute_data) = EX(prev_execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
OBJ_RELEASE(Z_OBJ(execute_data->This));
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -53697,6 +53697,7 @@ zend_leave_helper_SPEC_LABEL:
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);
#ifdef ZEND_PREFER_RELOAD
@@ -53705,7 +53706,6 @@ zend_leave_helper_SPEC_LABEL:
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. */
@@ -53749,6 +53749,7 @@ zend_leave_helper_SPEC_LABEL:
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);
#ifdef ZEND_PREFER_RELOAD
call_info = EX_CALL_INFO();
@@ -53759,7 +53760,6 @@ zend_leave_helper_SPEC_LABEL:
}
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_CLOSURE_OBJECT(EX(func)));
}