Skip to content

Commit 53d7c17

Browse files
committed
pdo_pgsql: escaped question marks inside dollar quoted strings
Allow "??" in dollar quoted strings for backwards compatibility, as it was a viable workaround to insert question marks without them being parsed as placeholders. Add a deprecation notice to tell that the escape is no longer necessary within dollar quotes and that its usage is deprecated. Ref bug #14244
1 parent 037243c commit 53d7c17

File tree

3 files changed

+63
-6
lines changed

3 files changed

+63
-6
lines changed

ext/pdo/pdo_sql_parser.re

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
9090
/* Matching closing quote found, end custom quoting */
9191
custom_quote.pos = NULL;
9292
custom_quote.len = 0;
93+
} else if (t == PDO_PARSER_ESCAPED_QUESTION) {
94+
/* An escaped question mark has been used inside a dollar quoted string, most likely as a workaround
95+
* as a single "?" would have been parsed as placeholder, due to the lack of support for dollar quoted
96+
* strings. For now, we emit a deprecation notice, but still process it */
97+
php_error_docref(NULL, E_DEPRECATED, "Escaping question marks inside dollar quoted strings is not required anymore and is deprecated");
98+
99+
goto placeholder;
93100
}
94101

95102
continue;
@@ -119,6 +126,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
119126
query_type |= PDO_PLACEHOLDER_POSITIONAL;
120127
}
121128

129+
placeholder:
122130
plc = emalloc(sizeof(*plc));
123131
memset(plc, 0, sizeof(*plc));
124132
plc->next = NULL;

ext/pdo_pgsql/tests/bug_14244.phpt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
PDO PgSQL Bug #14244 (Postgres sees parameters in a dollar-delimited string)
3+
--EXTENSIONS--
4+
pdo
5+
pdo_pgsql
6+
--SKIPIF--
7+
<?php
8+
require __DIR__ . '/config.inc';
9+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
10+
PDOTest::skip();
11+
?>
12+
--FILE--
13+
<?php
14+
echo "Test\n";
15+
16+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
17+
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt');
18+
$pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
19+
$pdo->setAttribute (\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
20+
21+
echo "Already working (see bug64953.phpt):\n";
22+
23+
$st = $pdo->prepare("SELECT '?' question");
24+
$st->execute();
25+
var_dump($st->fetch());
26+
27+
echo "Inside a dollar-quoted string:\n";
28+
29+
$st = $pdo->prepare("SELECT \$\$?\$\$ question");
30+
$st->execute();
31+
var_dump($st->fetch());
32+
33+
?>
34+
Done
35+
--EXPECT--
36+
Test
37+
Already working (see bug64953.phpt):
38+
array(1) {
39+
["question"]=>
40+
string(1) "?"
41+
}
42+
Inside a dollar-quoted string:
43+
array(1) {
44+
["question"]=>
45+
string(1) "?"
46+
}
47+
Done

ext/pdo_pgsql/tests/pdo_pgsql_parser.phpt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ PDOTest::skip();
1111
?>
1212
--FILE--
1313
<?php
14-
15-
require_once __DIR__ . "/config.inc";
16-
17-
$db = new PdoPgsql($config['ENV']['PDOTEST_DSN']);
14+
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
15+
$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
1816
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
1917

2018
$query = <<<'EOF'
@@ -25,10 +23,12 @@ UNION ALL
2523
SELECT U&'d\0061t\+000061? ' || ? AS b /* :name */
2624
UNION ALL
2725
SELECT $__$Is this a $$dollar$$ 'escaping'? $__$ || ? AS b -- ?
26+
UNION ALL
27+
SELECT $$Escaped question mark here?? $$ || ? AS b -- ?
2828
EOF;
2929

3030
$stmt = $db->prepare($query);
31-
$stmt->execute(['World', 'World', 'base', 'Yes']);
31+
$stmt->execute(['World', 'World', 'base', 'Yes', 'Yes']);
3232

3333
while ($row = $stmt->fetchColumn()) {
3434
var_dump($row);
@@ -56,10 +56,12 @@ try {
5656
}
5757

5858
?>
59-
--EXPECT--
59+
--EXPECTF--
60+
Deprecated: PDO::prepare(): Escaping question marks inside dollar quoted strings is not required anymore and is deprecated in %s on line %d
6061
string(14) "He'll'o? World"
6162
string(14) "He'll'o?\World"
6263
string(10) "data? base"
6364
string(36) "Is this a $$dollar$$ 'escaping'? Yes"
65+
string(31) "Escaped question mark here? Yes"
6466
bool(true)
6567
bool(true)

0 commit comments

Comments
 (0)