Skip to content

Commit 2671fc4

Browse files
committed
Fix GH-21639: Keep frameless call args stable during reentry
1 parent 54787f2 commit 2671fc4

13 files changed

Lines changed: 585 additions & 7 deletions

Zend/tests/gh21639.phpt

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
--TEST--
2+
GH-21639: Frameless calls keep volatile CV arguments alive during __toString()
3+
--FILE--
4+
<?php
5+
class ImplodeElement {
6+
public function __toString(): string {
7+
global $separator, $pieces;
8+
9+
$separator = null;
10+
$pieces = null;
11+
12+
return "C";
13+
}
14+
}
15+
16+
$separator = str_repeat(",", 1) . " ";
17+
$pieces = [new ImplodeElement(), 42];
18+
19+
var_dump(implode($separator, $pieces));
20+
var_dump($separator, $pieces);
21+
22+
class ImplodeElementWithoutSeparator {
23+
public function __toString(): string {
24+
global $oneArgPieces;
25+
26+
$oneArgPieces = null;
27+
28+
return "D";
29+
}
30+
}
31+
32+
$oneArgPieces = [new ImplodeElementWithoutSeparator(), 42];
33+
34+
var_dump(implode($oneArgPieces));
35+
var_dump($oneArgPieces);
36+
37+
class InArrayNeedle {
38+
public function __toString(): string {
39+
global $inArrayHaystack;
40+
41+
$inArrayHaystack = null;
42+
43+
return "needle";
44+
}
45+
}
46+
47+
$inArrayHaystack = [new InArrayNeedle()];
48+
49+
var_dump(in_array("needle", $inArrayHaystack));
50+
var_dump($inArrayHaystack);
51+
52+
class StrtrReplacement {
53+
public function __toString(): string {
54+
global $strtrReplacements;
55+
56+
$strtrReplacements = null;
57+
58+
return "b";
59+
}
60+
}
61+
62+
$strtrReplacements = ["a" => new StrtrReplacement()];
63+
64+
var_dump(strtr("a", $strtrReplacements));
65+
var_dump($strtrReplacements);
66+
67+
class StrReplaceSubject {
68+
public function __toString(): string {
69+
global $strReplaceSubject;
70+
71+
$strReplaceSubject = null;
72+
73+
return "a";
74+
}
75+
}
76+
77+
$strReplaceSubject = [new StrReplaceSubject(), "aa"];
78+
79+
var_dump(str_replace("a", "b", $strReplaceSubject));
80+
var_dump($strReplaceSubject);
81+
82+
class StrContainsHaystack {
83+
public function __toString(): string {
84+
global $strContainsNeedle;
85+
86+
$strContainsNeedle = null;
87+
88+
return "abc";
89+
}
90+
}
91+
92+
class StrContainsNeedle {
93+
public function __toString(): string {
94+
return "b";
95+
}
96+
}
97+
98+
$strContainsHaystack = new StrContainsHaystack();
99+
$strContainsNeedle = new StrContainsNeedle();
100+
101+
var_dump(str_contains($strContainsHaystack, $strContainsNeedle));
102+
var_dump($strContainsNeedle);
103+
?>
104+
--EXPECT--
105+
string(5) "C, 42"
106+
NULL
107+
NULL
108+
string(3) "D42"
109+
NULL
110+
bool(true)
111+
NULL
112+
string(1) "b"
113+
NULL
114+
array(2) {
115+
[0]=>
116+
string(1) "b"
117+
[1]=>
118+
string(2) "bb"
119+
}
120+
NULL
121+
bool(true)
122+
NULL

Zend/zend.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
812812
ZVAL_UNDEF(&executor_globals->user_error_handler);
813813
ZVAL_UNDEF(&executor_globals->user_exception_handler);
814814
executor_globals->current_execute_data = NULL;
815+
executor_globals->frameless_reentry_copies = NULL;
815816
executor_globals->current_module = NULL;
816817
executor_globals->exit_status = 0;
817818
#if XPFPA_HAVE_CW

0 commit comments

Comments
 (0)