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