Skip to content

Commit 4f23663

Browse files
committed
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix #80892: PDO::PARAM_INT is treated the same as PDO::PARAM_STR
2 parents 7f4784c + 340a067 commit 4f23663

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ PHP NEWS
3434
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
3535
(cmb)
3636

37+
- PDO_pgsql:
38+
. Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR).
39+
(Matteo)
40+
3741
- Session:
3842
. Fixed bug #80889 (Cannot set save handler when save_handler is invalid).
3943
(cmb)

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@
5252
#define VARCHARLABEL "varchar"
5353
#define VARCHAROID 1043
5454

55+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
56+
#define PG_INT32_MAX (0x7FFFFFFF)
57+
58+
#if defined(_MSC_VER)
59+
# define strtoll(s, f, b) _atoi64(s)
60+
#elif !defined(HAVE_STRTOLL)
61+
# if defined(HAVE_ATOLL)
62+
# define strtoll(s, f, b) atoll(s)
63+
# else
64+
# define strtoll(s, f, b) strtol(s, f, b)
65+
# endif
66+
#endif
67+
5568

5669

5770
static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
@@ -388,7 +401,16 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
388401
S->param_formats[param->paramno] = 0;
389402
}
390403

391-
if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
404+
if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT) {
405+
/* we need to check if the number requires bigints */
406+
long long val = strtoll(Z_STRVAL_P(parameter), NULL, 10);
407+
408+
if (val > PG_INT32_MAX || val < PG_INT32_MIN) {
409+
S->param_types[param->paramno] = INT8OID;
410+
} else {
411+
S->param_types[param->paramno] = INT4OID;
412+
}
413+
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
392414
S->param_types[param->paramno] = 0;
393415
S->param_formats[param->paramno] = 1;
394416
} else {

ext/pdo_pgsql/tests/bug_80892.phpt

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
Bug #80892 PDO::PARAM_INT is treated the same as PDO::PARAM_STR
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
6+
require __DIR__ . '/config.inc';
7+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
?>
10+
--FILE--
11+
<?php
12+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
13+
14+
/** @var PDO $db */
15+
$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
16+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
17+
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
18+
19+
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x bigint) RETURNS varchar AS $$ SELECT 'bigint' $$ LANGUAGE sql");
20+
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x int) RETURNS varchar AS $$ SELECT 'int' $$ LANGUAGE sql");
21+
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x text) RETURNS varchar AS $$ SELECT 'text' $$ LANGUAGE sql");
22+
23+
// Sanity check
24+
var_dump($db->query("SELECT bug80892(2147483648)")->fetchColumn());
25+
var_dump($db->query("SELECT bug80892(1)")->fetchColumn());
26+
var_dump($db->query("SELECT bug80892('1')")->fetchColumn());
27+
28+
// No binding
29+
$stmt = $db->prepare("SELECT bug80892(?)");
30+
$stmt->execute([1]);
31+
var_dump($stmt->fetchColumn());
32+
33+
// Bind int value as string
34+
$stmt = $db->prepare("SELECT bug80892(?)");
35+
$stmt->bindValue(1, 1, PDO::PARAM_STR);
36+
$stmt->execute();
37+
var_dump($stmt->fetchColumn());
38+
39+
// Bind int value as int
40+
$stmt = $db->prepare("SELECT bug80892(?)");
41+
$stmt->bindValue(1, 1, PDO::PARAM_INT);
42+
$stmt->execute();
43+
var_dump($stmt->fetchColumn());
44+
45+
// Bind string value as int
46+
$stmt = $db->prepare("SELECT bug80892(?)");
47+
$stmt->bindValue(1, '1', PDO::PARAM_INT);
48+
$stmt->execute();
49+
var_dump($stmt->fetchColumn());
50+
51+
// Bind bigint string value as int
52+
$stmt = $db->prepare("SELECT bug80892(?)");
53+
$stmt->bindValue(1, '2147483648', PDO::PARAM_INT);
54+
$stmt->execute();
55+
var_dump($stmt->fetchColumn());
56+
57+
// Bind negative bigint (string on 32bit) as int
58+
$stmt = $db->prepare("SELECT bug80892(?)");
59+
$stmt->bindValue(1, PHP_INT_SIZE == 4 ? '-33333333333' : -33333333333, PDO::PARAM_INT);
60+
$stmt->execute();
61+
var_dump($stmt->fetchColumn());
62+
63+
$db->exec("DROP FUNCTION bug80892 (bigint)");
64+
$db->exec("DROP FUNCTION bug80892 (int)");
65+
$db->exec("DROP FUNCTION bug80892 (text)");
66+
67+
?>
68+
--EXPECT--
69+
string(6) "bigint"
70+
string(3) "int"
71+
string(4) "text"
72+
string(4) "text"
73+
string(4) "text"
74+
string(3) "int"
75+
string(3) "int"
76+
string(6) "bigint"
77+
string(6) "bigint"

0 commit comments

Comments
 (0)