Skip to content

Commit c4f8b0b

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 changed from 256 byte to 2048 byte buf block.
1 parent d475fb8 commit c4f8b0b

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

ext/pdo_odbc/odbc_stmt.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
615615
/* tell ODBC to put it straight into our buffer, but only if it
616616
* isn't "long" data, and only if we haven't already bound a long
617617
* column. */
618-
if (colsize < 256 && !S->going_long) {
618+
if (colsize < 2048 && !S->going_long) {
619619
S->cols[colno].data = emalloc(colsize+1);
620620
S->cols[colno].is_long = 0;
621621

@@ -631,7 +631,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno)
631631
} else {
632632
/* allocate a smaller buffer to keep around for smaller
633633
* "long" columns */
634-
S->cols[colno].data = emalloc(256);
634+
S->cols[colno].data = emalloc(2048);
635635
S->going_long = 1;
636636
S->cols[colno].is_long = 1;
637637
}
@@ -657,14 +657,14 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo
657657
RETCODE rc;
658658

659659
/* fetch it into C->data, which is allocated with a length
660-
* of 256 bytes; if there is more to be had, we then allocate
660+
* of 2048 bytes; if there is more to be had, we then allocate
661661
* bigger buffer for the caller to free */
662662

663663
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
664-
256, &C->fetched_len);
664+
2048, &C->fetched_len);
665665
orig_fetched_len = C->fetched_len;
666666

667-
if (rc == SQL_SUCCESS && C->fetched_len < 256) {
667+
if (rc == SQL_SUCCESS && C->fetched_len < 2048) {
668668
/* all the data fit into our little buffer;
669669
* jump down to the generic bound data case */
670670
goto in_data;
@@ -684,16 +684,29 @@ 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+
* The behavior in this case is the same as before,
692+
* dividing the data into blocks. However, it has been
693+
* changed from 256 byte to 2048 byte block.
687694
*/
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 */
695+
ssize_t to_fetch_len;
696+
if (orig_fetched_len == SQL_NO_TOTAL) {
697+
to_fetch_len = C->datalen > 2047 ? 2047 : C->datalen;
698+
} else {
699+
to_fetch_len = orig_fetched_len;
700+
}
701+
ssize_t to_fetch_byte = to_fetch_len + 1;
702+
char *buf2 = emalloc(to_fetch_byte);
703+
zend_string *str = zend_string_init(C->data, to_fetch_byte, 0);
704+
size_t used = to_fetch_len;
692705

693706
do {
694707
C->fetched_len = 0;
695708
/* 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);
709+
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, to_fetch_byte, &C->fetched_len);
697710

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

705718
/* resize output buffer and reassemble block */
706-
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > orig_fetched_len)) {
719+
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > to_fetch_len)) {
707720
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
708721
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > n (greater than buf2's size)
709722
(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;
723+
str = zend_string_realloc(str, used + to_fetch_byte, 0);
724+
memcpy(ZSTR_VAL(str) + used, buf2, to_fetch_byte);
725+
used = used + to_fetch_len;
713726
} else if (rc==SQL_SUCCESS) {
714727
str = zend_string_realloc(str, used + C->fetched_len, 0);
715728
memcpy(ZSTR_VAL(str) + used, buf2, C->fetched_len);

0 commit comments

Comments
 (0)