mirror of
https://github.com/php/php-src.git
synced 2026-04-23 16:08:35 +02:00
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix #80783: PDO ODBC truncates BLOB records at every 256th byte
This commit is contained in:
@@ -14,6 +14,10 @@ PHP NEWS
|
||||
. Fixed bug #80861 (erronous array key overflow in 2D array with JIT).
|
||||
(Dmitry)
|
||||
|
||||
- PDO_ODBC:
|
||||
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
|
||||
(cmb)
|
||||
|
||||
01 Apr 2021, PHP 8.0.4
|
||||
|
||||
- Core:
|
||||
|
||||
@@ -650,6 +650,7 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
|
||||
/* if it is a column containing "long" data, perform late binding now */
|
||||
if (C->is_long) {
|
||||
SQLLEN orig_fetched_len = SQL_NULL_DATA;
|
||||
zend_ulong used = 0;
|
||||
char *buf;
|
||||
RETCODE rc;
|
||||
@@ -660,6 +661,7 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
|
||||
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
|
||||
256, &C->fetched_len);
|
||||
orig_fetched_len = C->fetched_len;
|
||||
|
||||
if (rc == SQL_SUCCESS) {
|
||||
/* all the data fit into our little buffer;
|
||||
@@ -671,7 +673,8 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
/* this is a 'long column'
|
||||
|
||||
read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks
|
||||
in order into the output buffer
|
||||
in order into the output buffer; 255 bytes are an optimistic assumption, since the driver may assert
|
||||
more or less NUL bytes at the end; we cater to that later, if actual length information is available
|
||||
|
||||
this loop has to work whether or not SQLGetData() provides the total column length.
|
||||
calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
|
||||
@@ -685,7 +688,14 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
do {
|
||||
C->fetched_len = 0;
|
||||
/* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */
|
||||
rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len);
|
||||
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, 256, &C->fetched_len);
|
||||
|
||||
/* adjust `used` in case we have length info from the driver */
|
||||
if (orig_fetched_len >= 0 && C->fetched_len >= 0) {
|
||||
SQLLEN fixed_used = orig_fetched_len - C->fetched_len;
|
||||
ZEND_ASSERT(fixed_used <= used + 1);
|
||||
used = fixed_used;
|
||||
}
|
||||
|
||||
/* resize output buffer and reassemble block */
|
||||
if (rc==SQL_SUCCESS_WITH_INFO) {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("CREATE TABLE bug80783 (name IMAGE)");
|
||||
|
||||
$string = str_repeat("0123456789", 50);
|
||||
$db->exec("INSERT INTO bug80783 VALUES('$string')");
|
||||
|
||||
$stmt = $db->prepare("SELECT name FROM bug80783");
|
||||
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
$stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
var_dump($data === bin2hex($string));
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("DROP TABLE bug80783");
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("CREATE TABLE bug80783a (name NVARCHAR(MAX))");
|
||||
|
||||
$string = str_repeat("0123456789", 50);
|
||||
$db->exec("INSERT INTO bug80783a VALUES('$string')");
|
||||
|
||||
$stmt = $db->prepare("SELECT name FROM bug80783a");
|
||||
$stmt->setAttribute(PDO::ODBC_ATTR_ASSUME_UTF8, true);
|
||||
$stmt->bindColumn(1, $data, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
var_dump($data === $string);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("DROP TABLE bug80783a");
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
Reference in New Issue
Block a user