xref: /PHP-8.3/ext/spl/tests/bug80111.phpt (revision 71cbef78)
1--TEST--
2Bug #80111: PHP SplDoublyLinkedList::offsetUnset UAF Sandbox Escape
3--FILE--
4<?php
5
6function i2s(&$s, $p, $i, $x=8)
7{
8    for($j=0;$j<$x;$j++)
9    {
10        $s[$p+$j] = chr($i & 0xff);
11        $i >>= 8;
12    }
13}
14
15class Trigger
16{
17    function __destruct()
18    {
19        global $s, $b;
20        # Add a reference afterwards
21        //$v = new SplDoublyLinkedList();
22        //$v->setIteratorMode(SplDoublyLinkedList::IT_MODE_DELETE);
23        # Remove element #2 from the list: this has no effect on
24        # intern->traverse_pointer, since it is removed from the list already
25        # The element, along with the zval, is freed
26        unset($s[0]);
27
28        $a = str_shuffle(str_repeat('A', 40-24-1));
29        # Build a fake zval (long, value: 12345678)
30        i2s($a, 0x00, 12345678); # ptr
31        i2s($a, 0x08, 4, 7); # type: long
32
33        var_dump($s->current());
34        $s->next();
35        # The value is our fake zval
36        var_dump($s->current());
37        print_r('DONE'."\n");
38    }
39}
40
41# Create a 3-item dllist
42$s = new SplDoublyLinkedList();
43
44# This is the UAF trigger
45$s->push(new Trigger());
46
47#$b = &$a;
48$s->push(3);
49
50# Points intern->traverse_pointer to our object element
51$s->rewind();
52#$s->next();
53
54# calls SplDoublyLinkedList::offsetUnset, which will remove the element from the
55# dllist, and then destruct the object, before clearing traverse_pointer
56unset($s[0]);
57
58?>
59--EXPECT--
60NULL
61NULL
62DONE
63