diff options
author | Matteo Beccati <mbeccati@php.net> | 2019-07-22 19:22:07 +0200 |
---|---|---|
committer | Matteo Beccati <mbeccati@php.net> | 2019-07-22 19:35:03 +0200 |
commit | b19fdc18a974929394c734d8b710d7a9ca3c9d3a (patch) | |
tree | 4229c2550e8806f528cfa82bf2342a8c54a72b9e /ext/pdo_pgsql | |
parent | 5d827c89cf0aa14f51e57cbe4d4e1e90475899b6 (diff) | |
download | php-git-b19fdc18a974929394c734d8b710d7a9ca3c9d3a.tar.gz |
Fix FR #71885 (Allow escaping question mark placeholders)
Diffstat (limited to 'ext/pdo_pgsql')
-rw-r--r-- | ext/pdo_pgsql/pgsql_driver.c | 46 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/bug71885.phpt | 46 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/bug71885_2.phpt | 57 |
3 files changed, 126 insertions, 23 deletions
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 15b2bd16c9..9c5df24ab5 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -256,36 +256,36 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len execute_only = H->disable_prepares; } - if (!emulate && PQprotocolVersion(H->server) > 2) { + if (!emulate && PQprotocolVersion(H->server) <= 2) { + emulate = 1; + } + + if (emulate) { + stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; + } else { stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED; stmt->named_rewrite_template = "$%d"; - ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); - - if (ret == 1) { - /* query was re-written */ - sql = nsql; - } else if (ret == -1) { - /* couldn't grok it */ - strcpy(dbh->error_code, stmt->error_code); - return 0; - } + } - if (!execute_only) { - /* prepared query: set the query name and defer the - actual prepare until the first execute call */ - spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter); - } + ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len); - if (nsql) { - S->query = nsql; - } else { - S->query = estrdup(sql); - } + if (ret == -1) { + /* couldn't grok it */ + strcpy(dbh->error_code, stmt->error_code); + return 0; + } else if (ret == 1) { + /* query was re-written */ + S->query = nsql; + } else { + S->query = estrdup(sql); + } - return 1; + if (!emulate && !execute_only) { + /* prepared query: set the query name and defer the + actual prepare until the first execute call */ + spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter); } - stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; return 1; } diff --git a/ext/pdo_pgsql/tests/bug71885.phpt b/ext/pdo_pgsql/tests/bug71885.phpt new file mode 100644 index 0000000000..ea5b1882ff --- /dev/null +++ b/ext/pdo_pgsql/tests/bug71885.phpt @@ -0,0 +1,46 @@ +--TEST-- +Request #71855 (PDO placeholder escaping) +--SKIPIF-- +<?php +if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded'); +require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +require_once dirname(__FILE__) . '/config.inc'; +PDOTest::skip(); +?> +--FILE-- +<?php +require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +require_once dirname(__FILE__) . '/config.inc'; +$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM); + +foreach ([false, true] as $emulate) { + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate); + + try { + $stmt = $db->prepare('select ?- lseg \'((-1,0),(1,0))\''); + $stmt->execute(); + } catch (PDOException $e) { + var_dump('ERR'); + } + + $stmt = $db->prepare('select ??- lseg \'((-1,0),(1,0))\''); + $stmt->execute(); + + var_dump($stmt->fetch()); +} + +?> +==OK== +--EXPECT-- +string(3) "ERR" +array(1) { + [0]=> + bool(true) +} +array(1) { + [0]=> + bool(true) +} +==OK== diff --git a/ext/pdo_pgsql/tests/bug71885_2.phpt b/ext/pdo_pgsql/tests/bug71885_2.phpt new file mode 100644 index 0000000000..f98e9ef785 --- /dev/null +++ b/ext/pdo_pgsql/tests/bug71885_2.phpt @@ -0,0 +1,57 @@ +--TEST-- +Request #71855 (PDO placeholder escaping, part 2) +--SKIPIF-- +<?php +if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded'); +require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +require_once dirname(__FILE__) . '/config.inc'; +PDOTest::skip(); + +$db = PDOTest::factory(); +if (version_compare($db->getAttribute(PDO::ATTR_SERVER_VERSION), '9.4.0') < 0) { + die("skip Requires 9.4+"); +} + +?> +--FILE-- +<?php +require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +require_once dirname(__FILE__) . '/config.inc'; +$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM); + +$jsonb = $db->quote(json_encode(['a' => 1])); + +foreach ([false, true] as $emulate) { + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate); + + $stmt = $db->prepare("SELECT {$jsonb}::jsonb ?? ?"); + $stmt->execute(['b']); + var_dump($stmt->fetch()); + + $stmt = $db->prepare("SELECT {$jsonb}::jsonb ???"); + $stmt->execute(['a']); + var_dump($stmt->fetch()); +} + +?> +==OK== +--EXPECT-- +array(1) { + [0]=> + bool(false) +} +array(1) { + [0]=> + bool(true) +} +array(1) { + [0]=> + bool(false) +} +array(1) { + [0]=> + bool(true) +} +==OK== |