Skip to content

Commit ec0ce49

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fix bug #76047
2 parents 37d0f7d + d422478 commit ec0ce49

File tree

5 files changed

+79
-13
lines changed

5 files changed

+79
-13
lines changed

Zend/tests/bug52361.phpt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ try {
2525
--EXPECTF--
2626
1. Exception: aaa in %sbug52361.php:5
2727
Stack trace:
28-
#0 %sbug52361.php(13): aaa->__destruct()
29-
#1 %sbug52361.php(16): bbb()
30-
#2 {main}
28+
#0 %sbug52361.php(16): aaa->__destruct()
29+
#1 {main}
3130
2. Exception: bbb in %sbug52361.php:13
3231
Stack trace:
3332
#0 %sbug52361.php(16): bbb()

Zend/tests/bug76047.phpt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
--TEST--
2+
Bug #76047: Use-after-free when accessing already destructed backtrace arguments
3+
--FILE--
4+
<?php
5+
6+
class Vuln {
7+
public $a;
8+
public function __destruct() {
9+
unset($this->a);
10+
$backtrace = (new Exception)->getTrace();
11+
var_dump($backtrace);
12+
}
13+
}
14+
15+
function test($arg) {
16+
$arg = str_shuffle(str_repeat('A', 79));
17+
$vuln = new Vuln();
18+
$vuln->a = $arg;
19+
}
20+
21+
function test2($arg) {
22+
$$arg = 1; // Trigger symbol table
23+
$arg = str_shuffle(str_repeat('A', 79));
24+
$vuln = new Vuln();
25+
$vuln->a = $arg;
26+
}
27+
28+
test('x');
29+
test2('x');
30+
31+
?>
32+
--EXPECTF--
33+
array(1) {
34+
[0]=>
35+
array(6) {
36+
["file"]=>
37+
string(%d) "%s"
38+
["line"]=>
39+
int(%d)
40+
["function"]=>
41+
string(10) "__destruct"
42+
["class"]=>
43+
string(4) "Vuln"
44+
["type"]=>
45+
string(2) "->"
46+
["args"]=>
47+
array(0) {
48+
}
49+
}
50+
}
51+
array(1) {
52+
[0]=>
53+
array(6) {
54+
["file"]=>
55+
string(%d) "%s"
56+
["line"]=>
57+
int(%d)
58+
["function"]=>
59+
string(10) "__destruct"
60+
["class"]=>
61+
string(4) "Vuln"
62+
["type"]=>
63+
string(2) "->"
64+
["args"]=>
65+
array(0) {
66+
}
67+
}
68+
}

Zend/tests/bug78973.phpt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,3 @@ test(new class {
1616
?>
1717
--EXPECTF--
1818
#0 class@anonymous->__destruct() called at [%s:%d]
19-
#1 test() called at [%s:%d]

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,12 +2754,12 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
27542754
SAVE_OPLINE();
27552755

27562756
if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
2757+
EG(current_execute_data) = EX(prev_execute_data);
27572758
i_free_compiled_variables(execute_data);
27582759

27592760
#ifdef ZEND_PREFER_RELOAD
27602761
call_info = EX_CALL_INFO();
27612762
#endif
2762-
EG(current_execute_data) = EX(prev_execute_data);
27632763
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
27642764
OBJ_RELEASE(Z_OBJ(execute_data->This));
27652765
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -2776,6 +2776,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
27762776
LOAD_NEXT_OPLINE();
27772777
ZEND_VM_LEAVE();
27782778
} else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
2779+
EG(current_execute_data) = EX(prev_execute_data);
27792780
i_free_compiled_variables(execute_data);
27802781

27812782
#ifdef ZEND_PREFER_RELOAD
@@ -2784,7 +2785,6 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
27842785
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
27852786
zend_clean_and_cache_symbol_table(EX(symbol_table));
27862787
}
2787-
EG(current_execute_data) = EX(prev_execute_data);
27882788

27892789
/* Free extra args before releasing the closure,
27902790
* as that may free the op_array. */
@@ -2828,6 +2828,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
28282828
ZEND_VM_LEAVE();
28292829
} else {
28302830
if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
2831+
EG(current_execute_data) = EX(prev_execute_data);
28312832
i_free_compiled_variables(execute_data);
28322833
#ifdef ZEND_PREFER_RELOAD
28332834
call_info = EX_CALL_INFO();
@@ -2838,7 +2839,6 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
28382839
}
28392840
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
28402841
}
2841-
EG(current_execute_data) = EX(prev_execute_data);
28422842
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
28432843
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
28442844
}

Zend/zend_vm_execute.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,12 +1100,12 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
11001100
SAVE_OPLINE();
11011101

11021102
if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
1103+
EG(current_execute_data) = EX(prev_execute_data);
11031104
i_free_compiled_variables(execute_data);
11041105

11051106
#ifdef ZEND_PREFER_RELOAD
11061107
call_info = EX_CALL_INFO();
11071108
#endif
1108-
EG(current_execute_data) = EX(prev_execute_data);
11091109
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
11101110
OBJ_RELEASE(Z_OBJ(execute_data->This));
11111111
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -1122,6 +1122,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
11221122
LOAD_NEXT_OPLINE();
11231123
ZEND_VM_LEAVE();
11241124
} else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
1125+
EG(current_execute_data) = EX(prev_execute_data);
11251126
i_free_compiled_variables(execute_data);
11261127

11271128
#ifdef ZEND_PREFER_RELOAD
@@ -1130,7 +1131,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
11301131
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
11311132
zend_clean_and_cache_symbol_table(EX(symbol_table));
11321133
}
1133-
EG(current_execute_data) = EX(prev_execute_data);
11341134

11351135
/* Free extra args before releasing the closure,
11361136
* as that may free the op_array. */
@@ -1174,6 +1174,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
11741174
ZEND_VM_LEAVE();
11751175
} else {
11761176
if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
1177+
EG(current_execute_data) = EX(prev_execute_data);
11771178
i_free_compiled_variables(execute_data);
11781179
#ifdef ZEND_PREFER_RELOAD
11791180
call_info = EX_CALL_INFO();
@@ -1184,7 +1185,6 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper
11841185
}
11851186
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
11861187
}
1187-
EG(current_execute_data) = EX(prev_execute_data);
11881188
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
11891189
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
11901190
}
@@ -51761,12 +51761,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5176151761
SAVE_OPLINE();
5176251762

5176351763
if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
51764+
EG(current_execute_data) = EX(prev_execute_data);
5176451765
i_free_compiled_variables(execute_data);
5176551766

5176651767
#ifdef ZEND_PREFER_RELOAD
5176751768
call_info = EX_CALL_INFO();
5176851769
#endif
51769-
EG(current_execute_data) = EX(prev_execute_data);
5177051770
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
5177151771
OBJ_RELEASE(Z_OBJ(execute_data->This));
5177251772
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -51783,6 +51783,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5178351783
LOAD_NEXT_OPLINE();
5178451784
ZEND_VM_LEAVE();
5178551785
} else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
51786+
EG(current_execute_data) = EX(prev_execute_data);
5178651787
i_free_compiled_variables(execute_data);
5178751788

5178851789
#ifdef ZEND_PREFER_RELOAD
@@ -51791,7 +51792,6 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5179151792
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
5179251793
zend_clean_and_cache_symbol_table(EX(symbol_table));
5179351794
}
51794-
EG(current_execute_data) = EX(prev_execute_data);
5179551795

5179651796
/* Free extra args before releasing the closure,
5179751797
* as that may free the op_array. */
@@ -51835,6 +51835,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5183551835
ZEND_VM_LEAVE();
5183651836
} else {
5183751837
if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
51838+
EG(current_execute_data) = EX(prev_execute_data);
5183851839
i_free_compiled_variables(execute_data);
5183951840
#ifdef ZEND_PREFER_RELOAD
5184051841
call_info = EX_CALL_INFO();
@@ -51845,7 +51846,6 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5184551846
}
5184651847
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
5184751848
}
51848-
EG(current_execute_data) = EX(prev_execute_data);
5184951849
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
5185051850
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
5185151851
}

0 commit comments

Comments
 (0)