Skip to content

Commit 340a067

Browse files
committed
Fix #80892: PDO::PARAM_INT is treated the same as PDO::PARAM_STR
1 parent da3a807 commit 340a067

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
@@ -25,6 +25,10 @@ PHP NEWS
2525
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
2626
(cmb)
2727

28+
- PDO_pgsql:
29+
. Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR).
30+
(Matteo)
31+
2832
- Session:
2933
. Fixed bug #80889 (Cannot set save handler when save_handler is invalid).
3034
(cmb)

ext/pdo_pgsql/pgsql_statement.c

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

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

5871

5972
static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
@@ -390,7 +403,16 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
390403
S->param_formats[param->paramno] = 0;
391404
}
392405

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