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
This commit is contained in:
Matteo Beccati 2024-05-20 14:17:13 +02:00
parent 037243ccd7
commit 53d7c17474
No known key found for this signature in database
3 changed files with 63 additions and 6 deletions

View File

@ -90,6 +90,13 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
/* Matching closing quote found, end custom quoting */
custom_quote.pos = NULL;
custom_quote.len = 0;
} else if (t == PDO_PARSER_ESCAPED_QUESTION) {
/* An escaped question mark has been used inside a dollar quoted string, most likely as a workaround
* as a single "?" would have been parsed as placeholder, due to the lack of support for dollar quoted
* strings. For now, we emit a deprecation notice, but still process it */
php_error_docref(NULL, E_DEPRECATED, "Escaping question marks inside dollar quoted strings is not required anymore and is deprecated");
goto placeholder;
}
continue;
@ -119,6 +126,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
query_type |= PDO_PLACEHOLDER_POSITIONAL;
}
placeholder:
plc = emalloc(sizeof(*plc));
memset(plc, 0, sizeof(*plc));
plc->next = NULL;

View File

@ -0,0 +1,47 @@
--TEST--
PDO PgSQL Bug #14244 (Postgres sees parameters in a dollar-delimited string)
--EXTENSIONS--
pdo
pdo_pgsql
--SKIPIF--
<?php
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
echo "Test\n";
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt');
$pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute (\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
echo "Already working (see bug64953.phpt):\n";
$st = $pdo->prepare("SELECT '?' question");
$st->execute();
var_dump($st->fetch());
echo "Inside a dollar-quoted string:\n";
$st = $pdo->prepare("SELECT \$\$?\$\$ question");
$st->execute();
var_dump($st->fetch());
?>
Done
--EXPECT--
Test
Already working (see bug64953.phpt):
array(1) {
["question"]=>
string(1) "?"
}
Inside a dollar-quoted string:
array(1) {
["question"]=>
string(1) "?"
}
Done

View File

@ -11,10 +11,8 @@ PDOTest::skip();
?>
--FILE--
<?php
require_once __DIR__ . "/config.inc";
$db = new PdoPgsql($config['ENV']['PDOTEST_DSN']);
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$query = <<<'EOF'
@ -25,10 +23,12 @@ UNION ALL
SELECT U&'d\0061t\+000061? ' || ? AS b /* :name */
UNION ALL
SELECT $__$Is this a $$dollar$$ 'escaping'? $__$ || ? AS b -- ?
UNION ALL
SELECT $$Escaped question mark here?? $$ || ? AS b -- ?
EOF;
$stmt = $db->prepare($query);
$stmt->execute(['World', 'World', 'base', 'Yes']);
$stmt->execute(['World', 'World', 'base', 'Yes', 'Yes']);
while ($row = $stmt->fetchColumn()) {
var_dump($row);
@ -56,10 +56,12 @@ try {
}
?>
--EXPECT--
--EXPECTF--
Deprecated: PDO::prepare(): Escaping question marks inside dollar quoted strings is not required anymore and is deprecated in %s on line %d
string(14) "He'll'o? World"
string(14) "He'll'o?\World"
string(10) "data? base"
string(36) "Is this a $$dollar$$ 'escaping'? Yes"
string(31) "Escaped question mark here? Yes"
bool(true)
bool(true)