Skip to content

Commit 7f83976

Browse files
committed
Fix #80460: ODBC doesn't account for SQL_NO_TOTAL indicator
The `StrLen_or_IndPtr` parameter usually may be `SQL_NO_TOTAL`; we need to cater to that possibility to avoid working with negative string lengths and other issues. A noteable exemption are calls to `SQLGetData()` which return `SQL_SUCCESS`; in that case `SQL_NO_TOTAL` can not occur. Closes GH-6809.
1 parent 66308af commit 7f83976

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PHP NEWS
1414
- FTP:
1515
. Fixed bug #80901 (Info leak in ftp extension). (cmb)
1616

17+
- ODBC:
18+
. Fixed bug #80460 (ODBC doesn't account for SQL_NO_TOTAL indicator). (cmb)
19+
1720
- pgsql:
1821
. Fixed php_pgsql_fd_cast() wrt. php_stream_can_cast(). (cmb)
1922

ext/odbc/php_odbc.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1814,6 +1814,9 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
18141814
} else if (result->values[i].vallen == SQL_NULL_DATA) {
18151815
ZVAL_NULL(&tmp);
18161816
break;
1817+
} else if (result->values[i].vallen == SQL_NO_TOTAL) {
1818+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1, rc);
1819+
ZVAL_FALSE(&tmp);
18171820
} else {
18181821
ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
18191822
}
@@ -1823,6 +1826,10 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
18231826
if (result->values[i].vallen == SQL_NULL_DATA) {
18241827
ZVAL_NULL(&tmp);
18251828
break;
1829+
} else if (result->values[i].vallen == SQL_NO_TOTAL) {
1830+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1, rc);
1831+
ZVAL_FALSE(&tmp);
1832+
break;
18261833
}
18271834
ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
18281835
break;
@@ -1970,6 +1977,9 @@ PHP_FUNCTION(odbc_fetch_into)
19701977
} else if (result->values[i].vallen == SQL_NULL_DATA) {
19711978
ZVAL_NULL(&tmp);
19721979
break;
1980+
} else if (result->values[i].vallen == SQL_NO_TOTAL) {
1981+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1, rc);
1982+
ZVAL_FALSE(&tmp);
19731983
} else {
19741984
ZVAL_STRINGL(&tmp, buf, result->values[i].vallen);
19751985
}
@@ -1979,6 +1989,10 @@ PHP_FUNCTION(odbc_fetch_into)
19791989
if (result->values[i].vallen == SQL_NULL_DATA) {
19801990
ZVAL_NULL(&tmp);
19811991
break;
1992+
} else if (result->values[i].vallen == SQL_NO_TOTAL) {
1993+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", i + 1, rc);
1994+
ZVAL_FALSE(&tmp);
1995+
break;
19821996
}
19831997
ZVAL_STRINGL(&tmp, result->values[i].value, result->values[i].vallen);
19841998
break;
@@ -2211,6 +2225,10 @@ PHP_FUNCTION(odbc_result)
22112225
} else if (result->values[field_ind].vallen == SQL_NULL_DATA) {
22122226
zend_string_efree(field_str);
22132227
RETURN_NULL();
2228+
} else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
2229+
zend_string_efree(field_str);
2230+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1, rc);
2231+
RETURN_FALSE;
22142232
}
22152233
/* Reduce fieldlen by 1 if we have char data. One day we might
22162234
have binary strings... */
@@ -2234,6 +2252,9 @@ PHP_FUNCTION(odbc_result)
22342252
default:
22352253
if (result->values[field_ind].vallen == SQL_NULL_DATA) {
22362254
RETURN_NULL();
2255+
} else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
2256+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1, rc);
2257+
RETURN_FALSE;
22372258
} else {
22382259
RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen);
22392260
}
@@ -2265,6 +2286,10 @@ PHP_FUNCTION(odbc_result)
22652286
if (result->values[field_ind].vallen == SQL_NULL_DATA) {
22662287
efree(field);
22672288
RETURN_NULL();
2289+
} else if (result->values[field_ind].vallen == SQL_NO_TOTAL) {
2290+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (driver cannot determine length)", field_ind + 1, rc);
2291+
efree(field);
2292+
RETURN_FALSE;
22682293
}
22692294
/* chop the trailing \0 by outputting only 4095 bytes */
22702295
PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen);
@@ -2370,7 +2395,14 @@ PHP_FUNCTION(odbc_result_all)
23702395
RETURN_FALSE;
23712396
}
23722397
if (rc == SQL_SUCCESS_WITH_INFO) {
2373-
PHPWRITE(buf, result->longreadlen);
2398+
if (result->values[i].vallen == SQL_NO_TOTAL) {
2399+
php_printf("</td></tr></table>");
2400+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (driver cannot determine length)", i + 1, rc);
2401+
efree(buf);
2402+
RETURN_FALSE;
2403+
} else {
2404+
PHPWRITE(buf, result->longreadlen);
2405+
}
23742406
} else if (rc != SQL_SUCCESS) {
23752407
php_printf("</td></tr></table>");
23762408
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (retcode %u)", i + 1, rc);
@@ -2387,6 +2419,9 @@ PHP_FUNCTION(odbc_result_all)
23872419
default:
23882420
if (result->values[i].vallen == SQL_NULL_DATA) {
23892421
php_printf("<td>NULL</td>");
2422+
} else if (result->values[i].vallen == SQL_NO_TOTAL) {
2423+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%zu (driver cannot determine length)", i + 1, rc);
2424+
php_printf("<td>FALSE</td>");
23902425
} else {
23912426
php_printf("<td>%s</td>", result->values[i].value);
23922427
}

0 commit comments

Comments
 (0)