mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
PDO_MYSQL: Properly quote binary strings
Closes GH-15949
This commit is contained in:
4
NEWS
4
NEWS
@@ -149,6 +149,10 @@ PHP NEWS
|
||||
- PCRE:
|
||||
. Fix UAF issues with PCRE after request shutdown. (nielsdos)
|
||||
|
||||
- PDO_MYSQL:
|
||||
. Fixed GH-15949 (PDO_MySQL not properly quoting PDO_PARAM_LOB binary
|
||||
data). (mbeccati, lcobucci)
|
||||
|
||||
- PDO_PGSQL:
|
||||
. Fixed GH-15986 (Double-free due to Pdo\Pgsql::setNoticeCallback()). (cmb,
|
||||
nielsdos)
|
||||
|
||||
@@ -184,6 +184,9 @@ PHP 8.4 UPGRADE NOTES
|
||||
- PDO_MYSQL:
|
||||
. getAttribute, ATTR_AUTOCOMMIT, ATTR_EMULATE_PREPARES, MYSQL_ATTR_DIRECT_QUERY have
|
||||
been changed to get values as bool.
|
||||
. Quoting a string with PARAM_LOB as type now outputs the string explicitly quoted
|
||||
as binary. This also affects parameters bound as PARAM_LOB when
|
||||
ATTR_EMULATE_PREPARES is enabled.
|
||||
|
||||
- PDO_PGSQL:
|
||||
. The DSN's credentials, when set, are given priority over their PDO
|
||||
|
||||
@@ -309,23 +309,29 @@ static zend_string* mysql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo
|
||||
{
|
||||
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
|
||||
bool use_national_character_set = 0;
|
||||
bool use_binary = 0;
|
||||
size_t quotedlen;
|
||||
|
||||
if (H->assume_national_character_set_strings) {
|
||||
use_national_character_set = 1;
|
||||
}
|
||||
if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
|
||||
use_national_character_set = 1;
|
||||
}
|
||||
if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) {
|
||||
use_national_character_set = 0;
|
||||
if ((paramtype & PDO_PARAM_LOB) == PDO_PARAM_LOB) {
|
||||
use_binary = 1;
|
||||
} else {
|
||||
if (H->assume_national_character_set_strings) {
|
||||
use_national_character_set = 1;
|
||||
}
|
||||
if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
|
||||
use_national_character_set = 1;
|
||||
}
|
||||
if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) {
|
||||
use_national_character_set = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PDO_DBG_ENTER("mysql_handle_quoter");
|
||||
PDO_DBG_INF_FMT("dbh=%p", dbh);
|
||||
PDO_DBG_INF_FMT("unquoted=%.*s", (int)ZSTR_LEN(unquoted), ZSTR_VAL(unquoted));
|
||||
|
||||
zend_string *quoted_str = zend_string_safe_alloc(2, ZSTR_LEN(unquoted), 3 + (use_national_character_set ? 1 : 0), false);
|
||||
zend_string *quoted_str = zend_string_safe_alloc(2, ZSTR_LEN(unquoted),
|
||||
3 + (use_national_character_set ? 1 : 0) + (use_binary ? 7 : 0), false);
|
||||
char *quoted = ZSTR_VAL(quoted_str);
|
||||
|
||||
if (use_national_character_set) {
|
||||
@@ -334,6 +340,11 @@ static zend_string* mysql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo
|
||||
quoted[1] = '\'';
|
||||
|
||||
++quotedlen; /* N prefix */
|
||||
} else if (use_binary) {
|
||||
quotedlen = mysql_real_escape_string_quote(H->server, quoted + 8, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
|
||||
memcpy(quoted, "_binary'", 8);
|
||||
|
||||
quotedlen += 7; /* _binary prefix */
|
||||
} else {
|
||||
quotedlen = mysql_real_escape_string_quote(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
|
||||
quoted[0] = '\'';
|
||||
|
||||
@@ -13,6 +13,10 @@ MySQLPDOTest::skip();
|
||||
$db = MySQLPDOTest::factory();
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
|
||||
|
||||
// Force the connection to utf8, which is enough to make the test fail
|
||||
// MySQL 5.6+ would be required for utf8mb4
|
||||
$db->exec("SET NAMES 'utf8'");
|
||||
|
||||
$content = '0191D886E6DC73E7AF1FEE7F99EC6235';
|
||||
|
||||
$statement = $db->prepare('SELECT HEX(?) as test');
|
||||
|
||||
28
ext/pdo_mysql/tests/pdo_mysql_quote_binary.phpt
Normal file
28
ext/pdo_mysql/tests/pdo_mysql_quote_binary.phpt
Normal file
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
MySQL PDO->quote(), properly handle binary data
|
||||
--EXTENSIONS--
|
||||
pdo_mysql
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||
MySQLPDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||
$db = MySQLPDOTest::factory();
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
|
||||
|
||||
// Force the connection to utf8, which is enough to make the test fail
|
||||
// MySQL 5.6+ would be required for utf8mb4
|
||||
$db->exec("SET NAMES 'utf8'");
|
||||
|
||||
$content = "\xC3\xA1\xC3";
|
||||
$quoted = $db->quote($content, PDO::PARAM_LOB);
|
||||
|
||||
var_dump($quoted);
|
||||
var_dump($db->query("SELECT HEX({$quoted})")->fetch(PDO::FETCH_NUM)[0]);
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "_binary'%s'"
|
||||
string(6) "C3A1C3"
|
||||
Reference in New Issue
Block a user