Skip to content

Commit 756dc19

Browse files
committed
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5: Fix bug #65946 - pdo_sql_parser.c permanently converts values bound to strings
2 parents 929bf11 + b3d522d commit 756dc19

File tree

3 files changed

+59
-20
lines changed

3 files changed

+59
-20
lines changed

ext/pdo/pdo_sql_parser.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -586,28 +586,30 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
586586
}
587587
plc->freeq = 1;
588588
} else {
589-
switch (Z_TYPE_P(param->parameter)) {
589+
zval tmp_param = *param->parameter;
590+
zval_copy_ctor(&tmp_param);
591+
switch (Z_TYPE(tmp_param)) {
590592
case IS_NULL:
591593
plc->quoted = "NULL";
592594
plc->qlen = sizeof("NULL")-1;
593595
plc->freeq = 0;
594596
break;
595597

596598
case IS_BOOL:
597-
convert_to_long(param->parameter);
598-
599+
convert_to_long(&tmp_param);
600+
/* fall through */
599601
case IS_LONG:
600602
case IS_DOUBLE:
601-
convert_to_string(param->parameter);
602-
plc->qlen = Z_STRLEN_P(param->parameter);
603-
plc->quoted = Z_STRVAL_P(param->parameter);
604-
plc->freeq = 0;
603+
convert_to_string(&tmp_param);
604+
plc->qlen = Z_STRLEN(tmp_param);
605+
plc->quoted = estrdup(Z_STRVAL(tmp_param));
606+
plc->freeq = 1;
605607
break;
606608

607609
default:
608-
convert_to_string(param->parameter);
609-
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
610-
Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen,
610+
convert_to_string(&tmp_param);
611+
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL(tmp_param),
612+
Z_STRLEN(tmp_param), &plc->quoted, &plc->qlen,
611613
param->param_type TSRMLS_CC)) {
612614
/* bork */
613615
ret = -1;
@@ -616,6 +618,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
616618
}
617619
plc->freeq = 1;
618620
}
621+
zval_dtor(&tmp_param);
619622
}
620623
} else {
621624
plc->quoted = Z_STRVAL_P(param->parameter);

ext/pdo/pdo_sql_parser.re

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,28 +228,30 @@ safe:
228228
}
229229
plc->freeq = 1;
230230
} else {
231-
switch (Z_TYPE_P(param->parameter)) {
231+
zval tmp_param = *param->parameter;
232+
zval_copy_ctor(&tmp_param);
233+
switch (Z_TYPE(tmp_param)) {
232234
case IS_NULL:
233235
plc->quoted = "NULL";
234236
plc->qlen = sizeof("NULL")-1;
235237
plc->freeq = 0;
236238
break;
237239

238240
case IS_BOOL:
239-
convert_to_long(param->parameter);
240-
241+
convert_to_long(&tmp_param);
242+
/* fall through */
241243
case IS_LONG:
242244
case IS_DOUBLE:
243-
convert_to_string(param->parameter);
244-
plc->qlen = Z_STRLEN_P(param->parameter);
245-
plc->quoted = Z_STRVAL_P(param->parameter);
246-
plc->freeq = 0;
245+
convert_to_string(&tmp_param);
246+
plc->qlen = Z_STRLEN(tmp_param);
247+
plc->quoted = estrdup(Z_STRVAL(tmp_param));
248+
plc->freeq = 1;
247249
break;
248250

249251
default:
250-
convert_to_string(param->parameter);
251-
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
252-
Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen,
252+
convert_to_string(&tmp_param);
253+
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL(tmp_param),
254+
Z_STRLEN(tmp_param), &plc->quoted, &plc->qlen,
253255
param->param_type TSRMLS_CC)) {
254256
/* bork */
255257
ret = -1;
@@ -258,6 +260,7 @@ safe:
258260
}
259261
plc->freeq = 1;
260262
}
263+
zval_dtor(&tmp_param);
261264
}
262265
} else {
263266
plc->quoted = Z_STRVAL_P(param->parameter);

ext/pdo/tests/bug65946.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Bug #65946 (pdo_sql_parser.c permanently converts values bound to strings)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo')) die('skip');
6+
$dir = getenv('REDIR_TEST_DIR');
7+
if (false == $dir) die('skip no driver');
8+
require_once $dir . 'pdo_test.inc';
9+
PDOTest::skip();
10+
?>
11+
--FILE--
12+
<?php
13+
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
14+
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
15+
$db = PDOTest::factory();
16+
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
17+
$db->exec('CREATE TABLE test(id int)');
18+
$db->exec('INSERT INTO test VALUES(1)');
19+
$db->exec('INSERT INTO test VALUES(2)');
20+
$stmt = $db->prepare('SELECT * FROM testtable LIMIT :limit');
21+
$stmt->bindValue('limit', 1, PDO::PARAM_INT);
22+
if(!($res = $stmt->execute())) var_dump($stmt->errorInfo());
23+
if(!($res = $stmt->execute())) var_dump($stmt->errorInfo());
24+
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
25+
?>
26+
--EXPECTF--
27+
array(1) {
28+
[0]=>
29+
array(1) {
30+
["id"]=>
31+
string(1) "2"
32+
}
33+
}

0 commit comments

Comments
 (0)