Bug #80783 [Com]: PDO ODBC truncates BLOB records at every 256th byte
| From: | horvath dot szabolcs at t-systems dot hu | Date: | Mon, 22 Feb 2021 10:15:59 +0000 |
| Subject: | Bug #80783 [Com]: PDO ODBC truncates BLOB records at every 256th byte | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-232315@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=80783&edit=1
ID: 80783
Comment by: horvath dot szabolcs at t-systems dot hu
Reported by: horvath dot szabolcs at t-systems dot hu
Summary: PDO ODBC truncates BLOB records at every 256th byte
Status: Open
Type: Bug
Package: PDO ODBC
Operating System: Red Hat Enterprise Linux Server
PHP Version: 7.3.27
Block user comment: N
Private report: N
New Comment:
Actual php-odbc trace:
[ODBC][26948][1613745870.512493][SQLConnect.c][3721]
Entry:
Connection = 0x55e05fd3fb90
Server Name = [ORACLETEST][length = 11 (SQL_NTS)]
User Name = [user][length = 11 (SQL_NTS)]
Authentication = [********][length = 8 (SQL_NTS)]
UNICODE Using encoding ASCII 'UTF-8' and UNICODE 'UTF16LE'
[ODBC][26948][1613745870.647085][SQLConnect.c][4299]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.647748][SQLAllocHandle.c][540]
Entry:
Handle Type = 3
Input Handle = 0x55e05fd3fb90
[ODBC][26948][1613745870.648513][SQLAllocHandle.c][1085]
Exit:[SQL_SUCCESS]
Output Handle = 0x55e06001e950
[ODBC][26948][1613745870.649134][SQLGetInfo.c][236]
Entry:
Connection = 0x55e05fd3fb90
Info Type = SQL_FETCH_DIRECTION (8)
Info Value = 0x7fff66837184
Buffer Length = 4
StrLen = (nil)
[ODBC][26948][1613745870.649701][SQLSetStmtOption.c][197]
Entry:
Statement = 0x55e06001e950
Option = SQL_ATTR_CURSOR_TYPE
Value = 3
[ODBC][26948][1613745870.650504][SQLSetStmtOption.c][477]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.650884][SQLExecDirect.c][240]
Entry:
Statement = 0x55e06001e950
SQL = [SELECT pdf FROM PAYROLL WHERE USER_ID = 999 AND ROWNUM = 1 ORDER BY
YEAR DESC, MONTH DESC][length = 89 (SQL_NTS)]
[ODBC][26948][1613745870.657670][SQLExecDirect.c][521]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.658258][SQLNumResultCols.c][156]
Entry:
Statement = 0x55e06001e950
Column Count = 0x7f4fed402358
[ODBC][26948][1613745870.658848][SQLNumResultCols.c][251]
Exit:[SQL_SUCCESS]
Count = 0x7f4fed402358 -> 1
[ODBC][26948][1613745870.659390][SQLColAttribute.c][294]
Entry:
Statement = 0x55e06001e950
Column Number = 1
Field Identifier = SQL_DESC_NAME
Character Attr = 0x7f4fed403280
Buffer Length = 256
String Length = 0x7fff66837092
Numeric Attribute = (nil)
[ODBC][26948][1613745870.659942][SQLColAttribute.c][709]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.660461][SQLColAttribute.c][294]
Entry:
Statement = 0x55e06001e950
Column Number = 1
Field Identifier = SQL_DESC_CONCISE_TYPE
Character Attr = (nil)
Buffer Length = 0
String Length = (nil)
Numeric Attribute = 0x7f4fed403390
[ODBC][26948][1613745870.660998][SQLColAttribute.c][709]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.661602][SQLExtendedFetch.c][166]
Entry:
Statement = 0x55e06001e950
Fetch Type = 1
Row = 1
PcRow = 0x7fff66837190
Row Status = 0x7fff66837170
[ODBC][26948][1613745870.666906][SQLExtendedFetch.c][339]
Exit:[SQL_SUCCESS]
[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
[ODBC][26948][1613745870.668576][SQLExtendedFetch.c][166]
Entry:
Statement = 0x55e06001e950
Fetch Type = 1
Row = 1
PcRow = 0x7fff66837190
Row Status = 0x7fff66837170
[ODBC][26948][1613745870.669176][SQLExtendedFetch.c][339]
Exit:[SQL_NO_DATA]
[ODBC][26948][1613745870.669937][SQLFreeStmt.c][144]
Entry:
Statement = 0x55e06001e950
Option = 1
[ODBC][26948][1613745870.670454][SQLFreeHandle.c][387]
Entry:
Handle Type = 3
Input Handle = 0x55e06001e950
[ODBC][26948][1613745870.671122][SQLFreeHandle.c][490]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745870.671663][SQLDisconnect.c][208]
Entry:
Connection = 0x55e05fd3fb90
[ODBC][26948][1613745871.630195][SQLDisconnect.c][379]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745871.630471][SQLFreeHandle.c][290]
Entry:
Handle Type = 2
Input Handle = 0x55e05fd3fb90
[ODBC][26948][1613745871.630712][SQLFreeHandle.c][339]
Exit:[SQL_SUCCESS]
[ODBC][26948][1613745871.630939][SQLFreeHandle.c][220]
Entry:
Handle Type = 1
Input Handle = 0x55e05fd305c0
Previous Comments:
------------------------------------------------------------------------
[2021-02-22 10:12:03] horvath dot szabolcs at t-systems dot hu
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 this bug report at https://bugs.php.net/bug.php?id=80783&edit=1