Skip to content

Commit 3dd02cc

Browse files
Fix buffer over-read corruption when short strings bound to CHAR(N) columns (DBC-18059) (#1054)
Signed-off-by: Balram Choudhary <bchoudhary@rocketsoftware.com>
1 parent e56836c commit 3dd02cc

1 file changed

Lines changed: 17 additions & 14 deletions

File tree

ibm_db.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8771,20 +8771,23 @@ static int _python_ibm_db_bind_data(stmt_handle *stmt_res, param_node *curr, PyO
87718771

87728772
if (isNewBuffer == 0)
87738773
{
8774-
/* actually make a copy, since this will uvalue will be freed explicitly */
8775-
SQLWCHAR *tmp = (SQLWCHAR *)ALLOC_N(SQLWCHAR, curr->ivalue + 1);
8776-
memcpy(tmp, curr->uvalue, (param_length + sizeof(SQLWCHAR)));
8774+
int col_wchars = curr->param_size;
8775+
SQLWCHAR *tmp = (SQLWCHAR *)ALLOC_N(SQLWCHAR, col_wchars + 1);
8776+
memset(tmp, 0, (col_wchars + 1) * sizeof(SQLWCHAR));
8777+
memcpy(tmp, curr->uvalue, param_length);
87778778
curr->uvalue = tmp;
8778-
snprintf(messageStr, sizeof(messageStr), "Copied uvalue to new buffer, tmp=%p", (void *)tmp);
8779+
snprintf(messageStr, sizeof(messageStr), "Copied uvalue to new buffer, tmp=%p, param_length=%d, col_wchars=%d", (void *)tmp, param_length, col_wchars);
87798780
LogMsg(DEBUG, messageStr);
87808781
}
87818782
else if (param_length <= curr->param_size)
87828783
{
8783-
SQLWCHAR *tmp = (SQLWCHAR *)ALLOC_N(SQLWCHAR, curr->ivalue + 1);
8784-
memcpy(tmp, curr->uvalue, (param_length + sizeof(SQLWCHAR)));
8784+
int col_wchars = curr->param_size;
8785+
SQLWCHAR *tmp = (SQLWCHAR *)ALLOC_N(SQLWCHAR, col_wchars + 1);
8786+
memset(tmp, 0, (col_wchars + 1) * sizeof(SQLWCHAR));
8787+
memcpy(tmp, curr->uvalue, param_length);
87858788
PyMem_Del(curr->uvalue);
87868789
curr->uvalue = tmp;
8787-
snprintf(messageStr, sizeof(messageStr), "Copied uvalue to new buffer with size adjustment, tmp=%p", (void *)tmp);
8790+
snprintf(messageStr, sizeof(messageStr), "Copied uvalue to new buffer with size adjustment, tmp=%p, param_length=%d, col_wchars=%d", (void *)tmp, param_length, col_wchars);
87888791
LogMsg(DEBUG, messageStr);
87898792
}
87908793

@@ -8870,8 +8873,7 @@ static int _python_ibm_db_bind_data(stmt_handle *stmt_res, param_node *curr, PyO
88708873
break;
88718874
case SQL_TYPE_TIMESTAMP:
88728875
case SQL_TYPE_TIMESTAMP_WITH_TIMEZONE:
8873-
snprintf(messageStr, sizeof(messageStr), "Handling SQL_TYPE_TIMESTAMP or SQL_TYPE_TIMESTAMP_WITH_TIMEZONE: param_length=%d, uvalue[10]=%c", param_length, curr->uvalue[10]);
8874-
LogMsg(DEBUG, messageStr);
8876+
LogMsg(INFO, "Handling SQL_TYPE_TIMESTAMP or SQL_TYPE_TIMESTAMP_WITH_TIMEZONE");
88758877
valueType = SQL_C_WCHAR;
88768878
if (param_length == 0)
88778879
{
@@ -8882,12 +8884,13 @@ static int _python_ibm_db_bind_data(stmt_handle *stmt_res, param_node *curr, PyO
88828884
else
88838885
{
88848886
curr->bind_indicator = param_length;
8885-
snprintf(messageStr, sizeof(messageStr), "SQL_TYPE_TIMESTAMP: bind_indicator=%d", curr->bind_indicator);
8887+
snprintf(messageStr, sizeof(messageStr), "SQL_TYPE_TIMESTAMP: param_length=%d, bind_indicator=%d", param_length, curr->bind_indicator);
88868888
LogMsg(DEBUG, messageStr);
8887-
}
8888-
if (curr->uvalue[10] == 'T')
8889-
{
8890-
curr->uvalue[10] = ' ';
8889+
if (param_length > 10 * (int)sizeof(SQLWCHAR) && curr->uvalue[10] == (SQLWCHAR)'T')
8890+
{
8891+
curr->uvalue[10] = (SQLWCHAR)' ';
8892+
LogMsg(DEBUG, "Replaced ISO 8601 'T' separator with space at uvalue[10]");
8893+
}
88918894
}
88928895
paramValuePtr = (SQLPOINTER)(curr->uvalue);
88938896
snprintf(messageStr, sizeof(messageStr), "SQL_TYPE_TIMESTAMP: paramValuePtr=%p", (void *)paramValuePtr);

0 commit comments

Comments
 (0)