xref: /PHP-8.0/ext/mysqli/tests/bug42378.phpt (revision e3e67b72)
1--TEST--
2Bug #42378 (bind_result memory exhaustion, SELECT column, FORMAT(...) AS _format)
3--SKIPIF--
4<?php
5require_once('skipif.inc');
6require_once('skipifconnectfailure.inc');
7?>
8--INI--
9memory_limit=83886080
10--FILE--
11<?php
12    require_once("connect.inc");
13
14    function create_table($link, $column, $min, $max, $engine, $offset) {
15
16        if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
17            printf("[%03d] Cannot drop table test, [%d] %s\n",
18                $offset,
19                mysqli_errno($link), mysqli_error($link));
20            return array();
21        }
22        print "$column\n";
23
24        $sql = sprintf("CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, col1 %s) ENGINE=%s",
25            $column, $engine);
26        if (!mysqli_query($link, $sql)) {
27            printf("[%03d] Cannot create table test, [%d] %s\n",
28                $offset + 1,
29                mysqli_errno($link), mysqli_error($link));
30            return array();
31        }
32
33        $values = array();
34        for ($i = 1; $i <= 100; $i++) {
35            $col1 = mt_rand($min, $max);
36            $values[$i] = $col1;
37            $sql = sprintf("INSERT INTO test(id, col1) VALUES (%d, %f)",
38                $i, $col1);
39            if (!mysqli_query($link, $sql)) {
40                printf("[%03d] Cannot insert data, [%d] %s\n",
41                    $offset + 2,
42                    mysqli_errno($link), mysqli_error($link));
43                return array();
44            }
45        }
46
47        return $values;
48    }
49
50    function test_format($link, $format, $from, $order_by, $expected, $offset) {
51
52        if (!$stmt = mysqli_stmt_init($link)) {
53            printf("[%03d] Cannot create PS, [%d] %s\n",
54                $offset,
55                mysqli_errno($link), mysqli_error($link));
56            return false;
57        }
58        print "$format\n";
59
60        if ($order_by)
61            $sql = sprintf('SELECT %s AS _format FROM %s ORDER BY %s', $format, $from, $order_by);
62        else
63            $sql = sprintf('SELECT %s AS _format FROM %s', $format, $from);
64
65        if (!mysqli_stmt_prepare($stmt, $sql)) {
66            printf("[%03d] Cannot prepare PS, [%d] %s\n",
67                $offset + 1,
68                mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
69            return false;
70        }
71
72        if (!mysqli_stmt_execute($stmt)) {
73            printf("[%03d] Cannot execute PS, [%d] %s\n",
74                $offset + 2,
75                mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
76            return false;
77        }
78
79        if (!mysqli_stmt_store_result($stmt)) {
80            printf("[%03d] Cannot store result set, [%d] %s\n",
81                $offset + 3,
82                mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
83            return false;
84        }
85
86        if (!is_array($expected)) {
87
88            $result = null;
89            if (!mysqli_stmt_bind_result($stmt, $result)) {
90                printf("[%03d] Cannot bind result, [%d] %s\n",
91                    $offset + 4,
92                    mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
93                return false;
94            }
95
96            if (!mysqli_stmt_fetch($stmt)) {
97                printf("[%03d] Cannot fetch result,, [%d] %s\n",
98                    $offset + 5,
99                    mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
100                return false;
101            }
102
103            if ($result !== $expected) {
104                printf("[%03d] Expecting %s/%s got %s/%s with %s - %s.\n",
105                    $offset + 6,
106                    gettype($expected), $expected,
107                    gettype($result), $result,
108                    $format, $sql);
109            }
110
111        } else {
112
113            $order_by_col = $result = null;
114            if (!is_null($order_by)) {
115                if (!mysqli_stmt_bind_result($stmt, $order_by_col, $result)) {
116                    printf("[%03d] Cannot bind result, [%d] %s\n",
117                        $offset + 7,
118                        mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
119                    return false;
120                }
121            } else {
122                if (!mysqli_stmt_bind_result($stmt, $result)) {
123                    printf("[%03d] Cannot bind result, [%d] %s\n",
124                        $offset + 7,
125                        mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
126                    return false;
127                }
128            }
129
130            foreach ($expected as $k => $v) {
131                if (!mysqli_stmt_fetch($stmt)) {
132                    break;
133                }
134                if ($result !== $v) {
135                    printf("[%03d] Row %d - expecting %s/%s got %s/%s [%s] with %s - %s.\n",
136                        $offset + 8,
137                        $k,
138                        gettype($v), $v,
139                        gettype($result), $result,
140                        $order_by_col,
141                        $format, $sql);
142                }
143            }
144
145        }
146
147        mysqli_stmt_free_result($stmt);
148        mysqli_stmt_close($stmt);
149
150        return true;
151    }
152
153    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
154        printf("[001] Cannot connect - [%d] %s\n",
155            mysqli_connect_errno(),
156            mysqli_connect_error());
157
158    /* create new table and select from it */
159    $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 90);
160    foreach ($expected as $k => $v)
161        $expected[$k] = number_format(round($v), 0, '.', ',');
162    test_format($link, 'FORMAT(col1, 0)', 'test', NULL, array(), 100);
163
164    $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 110);
165    foreach ($expected as $k => $v)
166        $expected[$k] = number_format(round($v), 0, '.', ',');
167    test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 120);
168
169    $expected = create_table($link, 'FLOAT UNSIGNED', 0, 10000, $engine, 130);
170    foreach ($expected as $k => $v)
171        $expected[$k] = number_format(round($v), 0, '.', ',');
172    test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 140);
173
174    $expected = create_table($link, 'DECIMAL(5,0)', -1000, 1000, $engine, 150);
175    foreach ($expected as $k => $v)
176        $expected[$k] = number_format(round($v), 0, '.', ',');
177    test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 160);
178
179    mysqli_close($link);
180    print "done!";
181?>
182--CLEAN--
183<?php
184	require_once("clean_table.inc");
185?>
186--EXPECT--
187FLOAT
188FORMAT(col1, 0)
189FLOAT
190id AS order_by_col, FORMAT(col1, 0)
191FLOAT UNSIGNED
192id AS order_by_col, FORMAT(col1, 0)
193DECIMAL(5,0)
194id AS order_by_col, FORMAT(col1, 0)
195done!
196