diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-01-31 10:29:26 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-01-31 10:29:45 +0100 |
commit | d422478f6d10691b63a8bc64072e929fd457bfe9 (patch) | |
tree | 3bde7527af020f1af3565e7252d9df9605296b7b | |
parent | db7193f31ea9d176214fc36cde0503864a75ab0d (diff) | |
parent | ef1e4891b47949c8dc0f9482eef9454a0ecdfa1d (diff) | |
download | php-git-d422478f6d10691b63a8bc64072e929fd457bfe9.tar.gz |
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
Fix bug #76047
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug52361.phpt | 5 | ||||
-rw-r--r-- | Zend/tests/bug76047.phpt | 68 | ||||
-rw-r--r-- | Zend/tests/bug78973.phpt | 1 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 6 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 12 |
6 files changed, 81 insertions, 13 deletions
@@ -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))); } |