@@ -684,16 +684,23 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo
684
684
* The extension previously tried getting it in 256
685
685
* byte blocks, but this could have created trouble
686
686
* 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.
687
693
*/
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 ;
692
699
693
700
do {
694
701
C -> fetched_len = 0 ;
695
702
/* 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 );
697
704
698
705
/* adjust `used` in case we have length info from the driver */
699
706
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
703
710
}
704
711
705
712
/* 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 )) {
707
714
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
708
715
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > n (greater than buf2's size)
709
716
(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 ;
713
720
} else if (rc == SQL_SUCCESS ) {
714
721
str = zend_string_realloc (str , used + C -> fetched_len , 0 );
715
722
memcpy (ZSTR_VAL (str ) + used , buf2 , C -> fetched_len );
0 commit comments