Edit report at https://bugs.php.net/bug.php?id=80460&edit=1
ID: 80460
Updated by: php-bugs@lists.php.net
Reported by: mirish at ibm dot com
Summary: ODBC doesn't account for SQL_NO_TOTAL indicator,
causing segmentation fault
-Status: Feedback
+Status: No Feedback
Type: Bug
Package: ODBC related
Operating System: RHEL 7.9
PHP Version: Irrelevant
Assigned To: cmb
Private report: N
New Comment:
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
Previous Comments:
------------------------------------------------------------------------
[2020-12-04 15:57:28] cmb@php.net
While the other bug report was indeed about SQL_NO_DATA, the fix
is supposed to cater to any result other than SQL_SUCCESS or
SQL_SUCCESS_WITH_INFO, and to return early in those cases.
Anyway, could you please generate a stack backtrace[1] and post it
here (or provide it somewhere else if it is very large)?
[1] <https://bugs.php.net/bugs-generating-backtrace.php>
------------------------------------------------------------------------
[2020-12-02 17:07:42] mirish at ibm dot com
It doesn't look like they are related. Bug #44618 seems to note that it should handle
SQL_NO_DATA, but that is a cursor indicator different from SQL_NO_TOTAL, which indicates that there
is data left to retrieve, but the driver doesn't know (or doesn't want to calculate) how
much data is left. As written, SQL_NO_TOTAL indicator (-4) is passed as a length to string
functions.
I can confirm that this segmentation fault occurs on 7.4.13.
------------------------------------------------------------------------
[2020-12-02 10:55:01] cmb@php.net
Isn't the second part basically a duplicate of bug #44618, which
is supposed to be fixed as of PHP 7.3.25 and 7.4.13?
------------------------------------------------------------------------
[2020-12-02 02:46:36] mirish at ibm dot com
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 this bug report at https://bugs.php.net/bug.php?id=80460&edit=1