Avoid state corruption via bailout · php/php-src@31c0ea7

GitHub

3 min read Original article ↗
Original file line numberDiff line numberDiff line change

@@ -16,9 +16,9 @@ if ($zend_mm_enabled === "0") {

1616

<?php

1717

ini_set('display_errors',true);

1818

$mb=148;

19-

$var = '';

19+

$var = [];

2020

for ($i=0; $i<=$mb; $i++) {

21-

$var.= str_repeat('a',1*1024*1024);

21+

$var[] = str_repeat('a',1*1024*1024);

2222

}

2323

?>

2424

--EXPECTF--

Original file line numberDiff line numberDiff line change

@@ -2,6 +2,7 @@

22

Bug #76846: Segfault in shutdown function after memory limit error

33

--INI--

44

memory_limit=33M

5+

zend.enable_gc=0

56

--SKIPIF--

67

<?php

78

$zend_mm_enabled = getenv("USE_ZEND_ALLOC");

@@ -12,13 +13,18 @@ if ($zend_mm_enabled === "0") {

1213

--FILE--

1314

<?php

1415
16+

class C {

17+

public $c;

18+

public function __construct() {

19+

$this->c = $this;

20+

}

21+

}

1522

register_shutdown_function(function() {

16-

new stdClass;

23+

new C;

1724

});

1825
19-

$ary = [];

2026

while (true) {

21-

$ary[] = new stdClass;

27+

new C;

2228

}

2329
2430

?>

Original file line numberDiff line numberDiff line change

@@ -2,6 +2,7 @@

22

Bug #54268 (Double free when destroy_zend_class fails)

33

--INI--

44

memory_limit=8M

5+

opcache.jit=disable

56

--SKIPIF--

67

<?php

78

$zend_mm_enabled = getenv("USE_ZEND_ALLOC");

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,21 @@

1+

--TEST--

2+

Backtrace args of a #[SensitiveParameter] variadic called with named arguments

3+

--FILE--

4+

<?php

5+

class E extends Exception {}

6+
7+

function outer(#[SensitiveParameter] ...$args) {

8+

return new E();

9+

}

10+
11+

var_dump(outer(a: 1, b: 'secret')->getTrace()[0]['args']);

12+

?>

13+

--EXPECT--

14+

array(2) {

15+

["a"]=>

16+

object(SensitiveParameterValue)#2 (0) {

17+

}

18+

["b"]=>

19+

object(SensitiveParameterValue)#3 (0) {

20+

}

21+

}

Original file line numberDiff line numberDiff line change

@@ -1,12 +1,5 @@

11

--TEST--

22

Fiber::getReturn() after bailout

3-

--SKIPIF--

4-

<?php

5-

$zend_mm_enabled = getenv("USE_ZEND_ALLOC");

6-

if ($zend_mm_enabled === "0") {

7-

die("skip Zend MM disabled");

8-

}

9-

?>

103

--FILE--

114

<?php

125

@@ -16,13 +9,13 @@ register_shutdown_function(static function (): void {

169

});

1710
1811

$fiber = new Fiber(static function (): void {

19-

str_repeat('X', PHP_INT_MAX);

12+

var_dump(new class { public function __debugInfo() { return ''; } }); // cause a bailout

2013

});

2114

$fiber->start();

2215
2316

?>

2417

--EXPECTF--

25-

Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) %sget-return-after-bailout.php on line %d

18+

Fatal error: __debuginfo() must return an array in %s on line %d

2619
2720

Fatal error: Uncaught FiberError: Cannot get fiber return value: The fiber exited with a fatal error in %sget-return-after-bailout.php:%d

2821

Stack trace:

Original file line numberDiff line numberDiff line change

@@ -8,7 +8,7 @@ if (PHP_OS_FAMILY === 'Windows') {

88

if (getenv("USE_ZEND_ALLOC") === "0") die("skip ZMM is disabled");

99

?>

1010

--INI--

11-

memory_limit=2M

11+

memory_limit=10M

1212

--FILE--

1313

<?php

1414

@@ -29,5 +29,4 @@ while (1) {

2929
3030

?>

3131

--EXPECTF--

32-

Success

33-

Fatal error: Allowed memory size of %s bytes exhausted%s(tried to allocate %s bytes) in %s on line %d

32+

Fatal error: Allowed memory size of 10485760 bytes exhausted %S(tried to allocate %d bytes) in %s on line %d

Original file line numberDiff line numberDiff line change

@@ -29,5 +29,4 @@ while (1) {

2929
3030

?>

3131

--EXPECTF--

32-

Success

33-

Fatal error: Allowed memory size of %s bytes exhausted%s(tried to allocate %s bytes) in %s on line %d

32+

Fatal error: Allowed memory size of 2097152 bytes exhausted %S(tried to allocate %d bytes) in %s on line %d

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,20 @@

1+

--TEST--

2+

OOM SplFixedArray::__unserialize()

3+

--INI--

4+

memory_limit=10M

5+

--FILE--

6+

<?php

7+
8+

$elems = [];

9+

for ($i = 0; $i < 64*1024; $i++) {

10+

$elems[] = "i:$i;N;";

11+

}

12+

$payload = 'O:13:"SplFixedArray":' . count($elems) . ':{' . implode('', $elems) . '}';

13+
14+

$pad = str_repeat('a', max(10*1024*1024 - memory_get_usage(true) - 512*1024, 1));

15+
16+

unserialize($payload);

17+
18+

?>

19+

--EXPECTF--

20+

Fatal error: Allowed memory size of 10485760 bytes exhausted %S(tried to allocate %d bytes) in %s on line 11

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,21 @@

1+

--TEST--

2+

OOM SplFixedArray::fromArray() 003

3+

--INI--

4+

memory_limit=16M

5+

--FILE--

6+

<?php

7+
8+

$a = new SplFixedArray();

9+

for ($i = 0; $i < 128*1024; $i++) {

10+

@$a->{$i} = 0;

11+

}

12+
13+

$pad = str_repeat('a', max(16*1024*1024 - memory_get_usage(true) - 512*1024, 1));

14+
15+

$a->__wakeup();

16+
17+

?>

18+

--EXPECTF--

19+

Deprecated: Method SplFixedArray::__wakeup() is deprecated since 8.4, this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize() in %s on line %d

20+
21+

Fatal error: Allowed memory size of 16777216 bytes exhausted %S(tried to allocate %d bytes) in %s on line 10

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,16 @@

1+

--TEST--

2+

OOM SplFixedArray copy ctor

3+

--INI--

4+

memory_limit=10M

5+

--FILE--

6+

<?php

7+
8+

$a = new SplFixedArray(64*1024);

9+
10+

$pad = str_repeat('a', max(10*1024*1024 - memory_get_usage(true) - 1*1024*1024, 1));

11+
12+

clone $a;

13+
14+

?>

15+

--EXPECTF--

16+

Fatal error: Allowed memory size of 10485760 bytes exhausted %S(tried to allocate %d bytes) in %s on line 7