Bug #80783 [NEW]: PDO ODBC truncates BLOB records at every 256th byte
| From: | horvath dot szabolcs at t-systems dot hu | Date: | Mon, 22 Feb 2021 10:12:03 +0000 |
| Subject: | Bug #80783 [NEW]: PDO ODBC truncates BLOB records at every 256th byte | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-232314@lists.php.net to get a copy of this message | ||
From: horvath dot szabolcs at t-systems dot hu
Operating system: Red Hat Enterprise Linux Server
PHP version: 7.3.27
Package: PDO ODBC
Bug Type: Bug
Bug description:PDO ODBC truncates BLOB records at every 256th byte
Description:
------------
Hi,
We're using PHP 7.3.20 from Red Hat Software Collections.
Although 7.3.27 is out there, I read thoroughly the changelog and
haven't found similar bug between 7.3.20 and 7.3.27.
There is a BLOB record in the database (Oracle 19c) which can be read
with php-odbc and can't with php-pdo.
We have a test case (see next chapter).
The Oracle ODBC trace outputs for both PDO and ODBC version have been
attached.
It seems that ODBC is capable for reading the BLOB in a 25.744 bytes
length chunk:
[ODBC][26948][1613745870.667436][SQLGetData.c][237]
Entry:
Statement = 0x55e06001e950
Column Number = 1
Target Type = -2 SQL_C_BINARY
Buffer Length = 131072
Target Value = 0x7f4fed496018
StrLen Or Ind = 0x7f4fed403388
[ODBC][26948][1613745870.668021][SQLGetData.c][545]
Exit:[SQL_SUCCESS]
Buffer = [BINARYDATA...]
Strlen Or Ind = 0x7f4fed403388 -> 25744
While PDO reads it in a loop with 256 byte length chunks:
[ODBC][32334][1613745953.051520][SQLGetData.c][545]
Exit:[SQL_SUCCESS_WITH_INFO]
Buffer =
[UDEyRGJHdDdYdys0US9BNGxPaWpTbmJ2Q1lBSFFOczBLVUx0TnNTaHBCcjF6WEZ2dm9XZWt3VUtRSmJGVmJmRHBnWWg0MlhjckdTZjJBWWkvMG14VWNYT3htUm5BTy9m]
Strlen Or Ind = 0x7f4fed4810d0 -> 25744
[ODBC][32334][1613745953.051771][SQLGetData.c][237]
Entry:
Statement = 0x55e05fe1fd30
Column Number = 1
Target Type = 1 SQL_CHAR
Buffer Length = 256
Target Value = 0x7f4fed48f100
StrLen Or Ind = 0x7f4fed4810d0
[ODBC][32334][1613745953.051995][SQLGetData.c][545]
Exit:[SQL_SUCCESS_WITH_INFO]
Buffer =
[Q3c3OGI2bnJycmVQMktmc2VNOWRmZ2c1ZVJDUUh0bFZNZCsyMWRjRHZnVTBrRjlCTE4wMWRKUTl4YjhkSDdoN3NBSTF0akdLT2ZvVGlTU3R6RnZJQmhSVGNGU3ZkRUxp]
Strlen Or Ind = 0x7f4fed4810d0 -> 25488
[ODBC][32334][1613745953.052224][SQLGetData.c][237]
Entry:
Statement = 0x55e05fe1fd30
Column Number = 1
Target Type = 1 SQL_CHAR
Buffer Length = 256
Target Value = 0x7f4fed48f100
StrLen Or Ind = 0x7f4fed4810d0
[ODBC][32334][1613745953.052459][SQLGetData.c][545]
Exit:[SQL_SUCCESS_WITH_INFO]
Buffer =
[K0wzTHZabE1KejhOcHpIblVuYXJzTktXTmdvWEw0YlNPa2l0b0FTNkNvOFVtc1hzYnNXTGErVnVDbXVXUHdLTGZTWGtIUHR0aDVwZU1LRS9DNDlONVhKSjN2S21zOFl2]
Strlen Or Ind = 0x7f4fed4810d0 -> 25232
I suspect at every 256 bytes length read there is one character
truncated.
Versions:
rh-php73-php-odbc-7.3.20-1.el7.x86_64
rh-php73-php-pdo-7.3.20-1.el7.x86_64
https://github.com/php/php-src/blob/master/ext/pdo_odbc/odbc_stmt.c
contains a lot of references for 256 bytes boundary.
Here is a similar php pdo_odbc issue
(https://github.com/microsoft/msphpsql/issues/1052) which matches, but
it has not been solved (the caller moved on to pdo_sqlsrv instead of
pdo_odbc)
Thank you in advance.
Best regards
Szabolcs Horvath
Test script:
---------------
1. ODBC version:
$conn = odbc_connect("ORACLETEST", "user", "password");
$query = "SELECT pdf FROM PAYROLL WHERE USER_ID = 999 AND ROWNUM = 1
ORDER BY YEAR DESC, MONTH DESC";
if(!$conn) die("Connection failed");
if($result = odbc_exec($conn, $query))
{
odbc_longreadlen($result, 131072);
while(odbc_fetch_row($result)){
print strlen(odbc_result($result,1));
}
}
2. PDO ODBC version:
$pdo = new PDO("odbc:ORACLETEST", "user", "password" );
$stmt = $pdo->prepare('SELECT pdf FROM PAYROLL WHERE USER_ID = 999 AND
ROWNUM = 1 ORDER BY YEAR DESC, MONTH DESC');
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
$stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND);
print strlen($data);
Expected result:
----------------
The actual data in the database is 25744 bytes long.
Actual result:
--------------
ODBC version returns with the length of 25744, and that's fine.
PDO ODBC version returns with the length of 25644 byte, which is 100
bytes smaller than expected.
--
Edit bug report at https://bugs.php.net/bug.php?id=80783&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=80783&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=80783&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=80783&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=80783&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=80783&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=80783&r=support
Expected behavior: https://bugs.php.net/fix.php?id=80783&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=80783&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=80783&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=80783&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=80783&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=80783&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=80783&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=80783&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=80783&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=80783&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=80783&r=mysqlcfg