diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index 1756714d8f1..1de8a618549 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -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; diff --git a/ext/pdo_pgsql/tests/bug_14244.phpt b/ext/pdo_pgsql/tests/bug_14244.phpt new file mode 100644 index 00000000000..2268ac9bedf --- /dev/null +++ b/ext/pdo_pgsql/tests/bug_14244.phpt @@ -0,0 +1,47 @@ +--TEST-- +PDO PgSQL Bug #14244 (Postgres sees parameters in a dollar-delimited string) +--EXTENSIONS-- +pdo +pdo_pgsql +--SKIPIF-- + +--FILE-- +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 diff --git a/ext/pdo_pgsql/tests/pdo_pgsql_parser.phpt b/ext/pdo_pgsql/tests/pdo_pgsql_parser.phpt index d4a4130c6fa..803123d1c88 100644 --- a/ext/pdo_pgsql/tests/pdo_pgsql_parser.phpt +++ b/ext/pdo_pgsql/tests/pdo_pgsql_parser.phpt @@ -11,10 +11,8 @@ PDOTest::skip(); ?> --FILE-- 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)