Skip to content

Commit 045dd07

Browse files
committed
odbc: check SQLColAttribute return codes in the field info functions
odbc_column_lengths() and odbc_field_type() ignored the SQLColAttribute return code and returned their output buffer regardless, so a driver that fails the call left odbc_field_len(), odbc_field_scale() and odbc_field_type() reporting uninitialized stack. Check the code, warn with the driver's own diagnostic, and return 0 or false instead. Closes GH-23601
1 parent 979c827 commit 045dd07

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ PHP NEWS
6464
replacement when a \k<name> backref has no closing delimiter.
6565
(Ilia Alshanetsky)
6666

67+
- ODBC:
68+
. Fixed odbc_field_len(), odbc_field_scale() and odbc_field_type()
69+
returning uninitialized memory when SQLColAttribute fails.
70+
(Ilia Alshanetsky)
71+
6772
- Opcache:
6873
. Fixed a crash when the huge page SHM remap discarded mappings outside the
6974
reserved address range. (Piotr Hałas)

ext/odbc/php_odbc.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ void odbc_bindcols(odbc_result *result)
683683
result->values[i].value_max_len = 0;
684684
colfieldid = SQL_COLUMN_DISPLAY_SIZE;
685685

686+
result->values[i].name[0] = '\0';
686687
rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), PHP_ODBC_SQL_DESC_NAME,
687688
result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
688689
result->values[i].coltype = 0;
@@ -809,10 +810,30 @@ void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
809810
}
810811
/* }}} */
811812

813+
static void odbc_colattribute_failed(odbc_result *result, zend_long pv_num)
814+
{
815+
#if defined(ODBCVER) && (ODBCVER >= 0x0300)
816+
SQLINTEGER diag_error;
817+
SQLCHAR diag_state[6];
818+
SQLCHAR diag_text[128];
819+
820+
memset(diag_state, '\0', sizeof(diag_state));
821+
memset(diag_text, '\0', sizeof(diag_text));
822+
if (SQL_SUCCESS == SQLGetDiagRec(SQL_HANDLE_STMT, result->stmt, 1, diag_state, &diag_error, diag_text, sizeof(diag_text), NULL)) {
823+
diag_state[sizeof(diag_state) - 1] = '\0';
824+
diag_text[sizeof(diag_text) - 1] = '\0';
825+
php_error_docref(NULL, E_WARNING, "SQLColAttribute failed for field #%d: [%s] %s", (int)pv_num, diag_state, diag_text);
826+
return;
827+
}
828+
#endif
829+
php_error_docref(NULL, E_WARNING, "SQLColAttribute failed for field #%d", (int)pv_num);
830+
}
831+
812832
/* {{{ odbc_column_lengths */
813833
void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
814834
{
815835
odbc_result *result;
836+
RETCODE rc;
816837
#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
817838
/* this seems to be necessary for Solid2.3 ( tested by
818839
* tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl)
@@ -849,7 +870,11 @@ void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
849870
RETURN_FALSE;
850871
}
851872

852-
PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
873+
rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT)(type ? SQL_COLUMN_SCALE : SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
874+
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
875+
odbc_colattribute_failed(result, pv_num);
876+
len = 0;
877+
}
853878

854879
RETURN_LONG(len);
855880
}
@@ -2597,6 +2622,7 @@ PHP_FUNCTION(odbc_field_type)
25972622
odbc_result *result;
25982623
char tmp[32];
25992624
SQLSMALLINT tmplen;
2625+
RETCODE rc;
26002626
zval *pv_res;
26012627
zend_long pv_num;
26022628

@@ -2622,7 +2648,13 @@ PHP_FUNCTION(odbc_field_type)
26222648
RETURN_FALSE;
26232649
}
26242650

2625-
PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
2651+
tmp[0] = '\0';
2652+
rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, sizeof(tmp) - 1, &tmplen, NULL);
2653+
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2654+
odbc_colattribute_failed(result, pv_num);
2655+
RETURN_FALSE;
2656+
}
2657+
26262658
RETURN_STRING(tmp);
26272659
}
26282660
/* }}} */

0 commit comments

Comments
 (0)