From 29fefc282933b4d9abdf2a9dd5ec377ff09470ad Mon Sep 17 00:00:00 2001 From: SAY-5 Date: Wed, 22 Apr 2026 23:08:33 -0700 Subject: [PATCH] fix(column): guard negative/oversized SQL_LEN in BindableColumn.Value BindableColumn.Value sliced c.Buffer[:c.Len] without checking sign or upper bound. Some drivers (observed on DB2 for CHAR columns when the DSN is configured for UTF-8 encoding, where the ODBC library miscalculates bounds for multi-byte UTF-8 values in fixed-length columns) return a negative SQL_LEN. The slice expression panicked with 'slice bounds out of range [:-4]', unwinding database/sql's Rows.Next through the caller's query handler. Reject any SQL_LEN that is negative or larger than len(c.Buffer) with an actionable error naming the column index and the out-of-range length. Happy-path values (0 <= c.Len <= len(c.Buffer)) are unchanged. Refs alexbrainman/odbc issue 224. Signed-off-by: SAY-5 --- column.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/column.go b/column.go index 31d891e..726738d 100644 --- a/column.go +++ b/column.go @@ -256,7 +256,15 @@ func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { if !c.IsVariableWidth && int(c.Len) != c.Size { return nil, fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size) } - return c.BaseColumn.Value(c.Buffer[:c.Len]) + // Guard against drivers (seen with DB2 on CHAR columns with UTF-8 + // DSN encoding) that return a negative SQL_LEN or one larger than + // the bound buffer. The old code sliced c.Buffer[:c.Len] directly + // and panicked with 'slice bounds out of range [:-4]'. + n := int(c.Len) + if n < 0 || n > len(c.Buffer) { + return nil, fmt.Errorf("column #%d returned length %d out of range for buffer size %d", idx, c.Len, len(c.Buffer)) + } + return c.BaseColumn.Value(c.Buffer[:n]) } // NonBindableColumn provide access to columns, that can't be bound.