From: mirish at ibm dot com
Operating system: RHEL 7.9
PHP version: Irrelevant
Package: ODBC related
Bug Type: Bug
Bug description:ODBC doesn't account for SQL_NO_TOTAL indicator, causing segmentation fault
Description:
------------
The ODBC extension (ext/odbc/php_odbc.c) causes a segmentation fault
when SQL_NO_TOTAL indicator is returned to a bound column from a call to
SQLFetch and similar functions.
There are two major issues:
1. There is an assumption that the number of bytes returned from a call
to SQLColAttribute with a type of SQL_DESC_OCTET_LENGTH will return the
number of bytes required to store the value. There are cases when data
is stored in an encoding which stores character data in a single byte,
which then needs to be converted to variable multi-byte when SQLFetch is
actually called (eg. EBCDIC 278 to UTF8 conversion). This might be a
broken driver implementation on our part, but the ODBC docs are rather
thin and at times seem contradictory on this point.
This will cause a buffer to be allocated of size X, where up to X * 4
may be needed to store a string. There is a variable in the code
(charextraalloc) to allocate buffers of this size, but none of the
checks work for ODBC v 3.0+ drivers. When the buffer is too small, the
driver may return SQL_NO_TOTAL when in the StrLen_or_IndPtr, as it
didn't have enough space for the column, and might not know how many
bytes are left.
2. The bigger issue is that calls to SQLFetch can return SQL_NO_TOTAL to
the StrLen_or_IndPtr stored on SQLBindCol when the buffer bound isn't
large enough for the data, but the code isn't checking for this.
Instead, the code checks if the value of StrLen_or_IndPtr is
SQL_NULL_DATA and assigns a value to null. If it isn't SQL_NULL_DATA, it
assumes that it holds the length of the string, then calls functions
like ZVAL_STRINGL and RETURN_STRINGL with SQL_NO_TOTAL (which evaluates
to -4) as the length. Trying to create a string with length of -4 causes
a segmentation fault, which causes the program to crash.
As mentioned, the first issue might be a problem in driver
implementation, but the second definitely needs to be fixed.
SQL_NO_TOTAL is definitely a valid StrLen_or_IndPtr value, and there are
no checks for it in the code, causing a segfault.
--
Edit bug report at https://bugs.php.net/bug.php?id=80460&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=80460&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=80460&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=80460&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=80460&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=80460&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=80460&r=support
Expected behavior: https://bugs.php.net/fix.php?id=80460&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=80460&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=80460&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=80460&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=80460&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=80460&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=80460&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=80460&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=80460&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=80460&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=80460&r=mysqlcfg