Skip to content

Commit 487e17d

Browse files
dstogoviluuu1994
authored andcommitted
Delay freeing of overwritten values in assignments
Fixes GH-10168
1 parent a3e44bb commit 487e17d

20 files changed

+1587
-203
lines changed

Zend/tests/gh10168_1.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): array variation
3+
--FILE--
4+
<?php
5+
6+
class Test
7+
{
8+
static $instances;
9+
public function __construct() {
10+
var_dump(self::$instances[NULL] = $this);
11+
var_dump(self::$instances);
12+
}
13+
14+
function __destruct() {
15+
unset(self::$instances[NULL]);
16+
}
17+
}
18+
new Test();
19+
new Test();
20+
21+
?>
22+
--EXPECT--
23+
object(Test)#1 (0) {
24+
}
25+
array(1) {
26+
[""]=>
27+
object(Test)#1 (0) {
28+
}
29+
}
30+
object(Test)#2 (0) {
31+
}
32+
array(0) {
33+
}

Zend/tests/gh10168_10.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed static prop ref
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
static ?Test $a = null;
8+
function __construct() {
9+
var_dump(self::$a = &$this);
10+
}
11+
function __destruct() {
12+
self::$a = null;
13+
}
14+
}
15+
new Test;
16+
new Test;
17+
18+
?>
19+
--EXPECT--
20+
object(Test)#1 (0) {
21+
}
22+
NULL

Zend/tests/gh10168_11.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): global by ref val error
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
function __destruct(){
8+
unset($GLOBALS['a']);
9+
}
10+
}
11+
12+
function returnsVal() {
13+
return 42;
14+
}
15+
$a = new Test;
16+
var_dump($a =& returnsVal());
17+
18+
?>
19+
--EXPECTF--
20+
Notice: Only variables should be assigned by reference in %s on line %d
21+
int(42)

Zend/tests/gh10168_12.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign static prop ref
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
static $a = null;
8+
function __construct() {
9+
var_dump(self::$a = &$this);
10+
}
11+
function __destruct() {
12+
self::$a = null;
13+
}
14+
}
15+
new Test;
16+
new Test;
17+
18+
?>
19+
--EXPECT--
20+
object(Test)#1 (0) {
21+
}
22+
NULL

Zend/tests/gh10168_13.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign prop ref
3+
--FILE--
4+
<?php
5+
6+
class Box {
7+
public $storage;
8+
}
9+
10+
$box = new Box();
11+
12+
class Test
13+
{
14+
public function __construct() {
15+
global $box;
16+
var_dump($box->storage = &$this);
17+
}
18+
19+
function __destruct() {
20+
global $box;
21+
var_dump($box->storage);
22+
$box->storage = null;
23+
}
24+
}
25+
new Test();
26+
new Test();
27+
28+
?>
29+
--EXPECT--
30+
object(Test)#2 (0) {
31+
}
32+
object(Test)#3 (0) {
33+
}
34+
NULL
35+
NULL

Zend/tests/gh10168_14.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop ref
3+
--FILE--
4+
<?php
5+
6+
class Box {
7+
public ?Test $storage = null;
8+
}
9+
10+
$box = new Box();
11+
12+
class Test
13+
{
14+
public function __construct() {
15+
global $box;
16+
var_dump($box->storage = &$this);
17+
}
18+
19+
function __destruct() {
20+
global $box;
21+
var_dump($box->storage);
22+
$box->storage = null;
23+
}
24+
}
25+
new Test();
26+
new Test();
27+
28+
?>
29+
--EXPECT--
30+
object(Test)#2 (0) {
31+
}
32+
object(Test)#3 (0) {
33+
}
34+
NULL
35+
NULL

Zend/tests/gh10168_15.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): global by ref
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
function __destruct(){
8+
unset($GLOBALS['a']);
9+
}
10+
}
11+
12+
function &returnsVal() {
13+
$a = 42;
14+
return $a;
15+
}
16+
$a = new Test;
17+
var_dump($a =& returnsVal());
18+
19+
?>
20+
--EXPECT--
21+
int(42)

Zend/tests/gh10168_2.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign global variation
3+
--FILE--
4+
<?php
5+
6+
$a = null;
7+
8+
class Test
9+
{
10+
public function __construct() {
11+
var_dump($GLOBALS['a'] = $this);
12+
// Destructor called after comparison, so a will be NULL
13+
var_dump($GLOBALS['a']);
14+
}
15+
16+
function __destruct() {
17+
unset($GLOBALS['a']);
18+
}
19+
}
20+
new Test();
21+
new Test();
22+
23+
?>
24+
--EXPECTF--
25+
object(Test)#1 (0) {
26+
}
27+
object(Test)#1 (0) {
28+
}
29+
object(Test)#2 (0) {
30+
}
31+
32+
Warning: Undefined global variable $a in %s on line %d
33+
NULL

Zend/tests/gh10168_3.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed static prop
3+
--FILE--
4+
<?php
5+
class Test
6+
{
7+
static ?Test $a = null;
8+
9+
public function __construct() {
10+
static $i = 0;
11+
$i++;
12+
if ($i === 1) {
13+
var_dump(self::$a = $this);
14+
} else {
15+
// Avoid cache slot, triggering write_property
16+
var_dump(self::$a = $this);
17+
}
18+
}
19+
20+
function __destruct() {
21+
var_dump(self::$a);
22+
self::$a = null;
23+
}
24+
}
25+
new Test();
26+
new Test();
27+
28+
?>
29+
--EXPECT--
30+
object(Test)#1 (0) {
31+
}
32+
object(Test)#2 (0) {
33+
}
34+
object(Test)#2 (0) {
35+
}
36+
NULL

Zend/tests/gh10168_4.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign prop
3+
--FILE--
4+
<?php
5+
6+
class Box {
7+
public $storage;
8+
}
9+
10+
$box = new Box();
11+
12+
class Test
13+
{
14+
public function __construct() {
15+
global $box;
16+
var_dump($box->storage = $this);
17+
}
18+
19+
function __destruct() {
20+
global $box;
21+
var_dump($box->storage);
22+
$box->storage = null;
23+
}
24+
}
25+
new Test();
26+
new Test();
27+
28+
?>
29+
--EXPECT--
30+
object(Test)#2 (0) {
31+
}
32+
object(Test)#3 (0) {
33+
}
34+
object(Test)#3 (0) {
35+
}
36+
NULL

Zend/tests/gh10168_5.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): allocated assignment in destructor
3+
--FILE--
4+
<?php
5+
6+
class Foo {}
7+
8+
class Test
9+
{
10+
static Test|Foo|null $a = null;
11+
12+
public function __construct() {
13+
var_dump(self::$a = $this);
14+
}
15+
16+
function __destruct() {
17+
var_dump(self::$a = new Foo());
18+
}
19+
}
20+
new Test();
21+
new Test();
22+
23+
?>
24+
--EXPECT--
25+
object(Test)#1 (0) {
26+
}
27+
object(Foo)#3 (0) {
28+
}
29+
object(Test)#2 (0) {
30+
}
31+
object(Foo)#1 (0) {
32+
}

Zend/tests/gh10168_6.phpt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop without cache slot
3+
--XFAIL--
4+
--FILE--
5+
<?php
6+
7+
class Box {
8+
public $storage;
9+
}
10+
11+
$box = new Box();
12+
13+
class Test
14+
{
15+
public function __construct() {
16+
static $i = 0;
17+
$i++;
18+
global $box;
19+
if ($i === 1) {
20+
var_dump($box->storage = $this);
21+
} else {
22+
// Avoid cache slot, triggering write_property
23+
var_dump($box->storage = $this);
24+
}
25+
}
26+
27+
function __destruct() {
28+
global $box;
29+
$box->storage = null;
30+
}
31+
}
32+
new Test();
33+
new Test();
34+
35+
?>
36+
--EXPECT--
37+
object(Test)#2 (0) {
38+
}
39+
object(Test)#3 (0) {
40+
}

0 commit comments

Comments
 (0)