Skip to content

Commit c93fcfa

Browse files
committed
change to separate by 256 bytes, when C->fetched_len == SQL_NO_TOTAL
change to separate by 256 bytes, when C->fetched_len == SQL_NO_TOTAL
1 parent d475fb8 commit c93fcfa

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

ext/pdo_odbc/odbc_stmt.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -684,16 +684,23 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo
684684
* The extension previously tried getting it in 256
685685
* byte blocks, but this could have created trouble
686686
* with some drivers.
687+
*
688+
* However, depending on the driver, fetched_len may
689+
* not contain the number of bytes and SQL_NO_TOTAL
690+
* may be passed.
691+
* In that case, the operation will be the same as
692+
* before, dividing the data into 256-byte blocks.
687693
*/
688-
SQLLEN to_fetch_len = orig_fetched_len + 1; /* for 0 at end */
689-
char *buf2 = emalloc(to_fetch_len);
690-
zend_string *str = zend_string_init(C->data, to_fetch_len, 0);
691-
size_t used = orig_fetched_len; /* not n + 1; the driver NUL terminated the buffer */
694+
ssize_t to_fetch_len = orig_fetched_len == SQL_NO_TOTAL ? 255 : orig_fetched_len;
695+
ssize_t to_fetch_byte = to_fetch_len + 1;
696+
char *buf2 = emalloc(to_fetch_byte);
697+
zend_string *str = zend_string_init(C->data, to_fetch_byte, 0);
698+
size_t used = to_fetch_len;
692699

693700
do {
694701
C->fetched_len = 0;
695702
/* read block. n + 1 bytes => n bytes are actually read, the last 1 is NULL */
696-
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, to_fetch_len, &C->fetched_len);
703+
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, to_fetch_byte, &C->fetched_len);
697704

698705
/* adjust `used` in case we have length info from the driver */
699706
if (orig_fetched_len >= 0 && C->fetched_len >= 0) {
@@ -703,13 +710,13 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo
703710
}
704711

705712
/* resize output buffer and reassemble block */
706-
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > orig_fetched_len)) {
713+
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > to_fetch_len)) {
707714
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
708715
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > n (greater than buf2's size)
709716
(if a driver fails to follow that and wrote less than n bytes to buf2, this will AV or read garbage into buf) */
710-
str = zend_string_realloc(str, used + to_fetch_len, 0);
711-
memcpy(ZSTR_VAL(str) + used, buf2, to_fetch_len);
712-
used = used + orig_fetched_len;
717+
str = zend_string_realloc(str, used + to_fetch_byte, 0);
718+
memcpy(ZSTR_VAL(str) + used, buf2, to_fetch_byte);
719+
used = used + to_fetch_len;
713720
} else if (rc==SQL_SUCCESS) {
714721
str = zend_string_realloc(str, used + C->fetched_len, 0);
715722
memcpy(ZSTR_VAL(str) + used, buf2, C->fetched_len);

0 commit comments

Comments
 (0)