Bug #80460 [Asn->Fbk]: ODBC doesn't account for SQL_NO_TOTAL indicator, causing segmentation fault

From: Date: Fri, 04 Dec 2020 15:57:28 +0000
Subject: Bug #80460 [Asn->Fbk]: ODBC doesn't account for SQL_NO_TOTAL indicator, causing segmentation fault
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-230855@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80460&edit=1

 ID:                 80460
 Updated by:         cmb@php.net
 Reported by:        mirish at ibm dot com
 Summary:            ODBC doesn't account for SQL_NO_TOTAL indicator,
                     causing segmentation fault
-Status:             Assigned
+Status:             Feedback
 Type:               Bug
 Package:            ODBC related
 Operating System:   RHEL 7.9
 PHP Version:        Irrelevant
 Assigned To:        cmb
 Block user comment: N
 Private report:     N

 New Comment:

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>


Previous Comments:
------------------------------------------------------------------------
[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


Thread (19 messages)

« previous php.bugs (#230855) next »