From 91e66999fb7a7847a4a340f773471546aa6823c4 Mon Sep 17 00:00:00 2001 From: Zihan Dai <99155080+PDGGK@users.noreply.github.com> Date: Wed, 22 Jul 2026 04:03:15 +1000 Subject: [PATCH] Fix off-by-one bounds check in Tablet.SetValueAt/GetValueAt The columnIndex/rowIndex guards used `> len(measurementSchemas)` and `> maxRowNumber`, which let the exact boundary index (columnIndex == len, rowIndex == maxRowNumber) escape the check. Since the schema and value slices have exactly those lengths, the boundary index then hit a runtime "index out of range" panic instead of the intended "illegal argument" error that both methods are meant to return. Change all four guards to `>=`, and add exact-boundary regression cases to TestTablet_SetValueAt / TestTablet_GetValueAt. Signed-off-by: Zihan Dai <99155080+PDGGK@users.noreply.github.com> --- client/tablet.go | 8 ++++---- client/tablet_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/client/tablet.go b/client/tablet.go index e161ddc..04d828b 100644 --- a/client/tablet.go +++ b/client/tablet.go @@ -110,11 +110,11 @@ func (t *Tablet) SetTimestamp(timestamp int64, rowIndex int) { func (t *Tablet) SetValueAt(value interface{}, columnIndex, rowIndex int) error { - if columnIndex < 0 || columnIndex > len(t.measurementSchemas) { + if columnIndex < 0 || columnIndex >= len(t.measurementSchemas) { return fmt.Errorf("illegal argument columnIndex %d", columnIndex) } - if rowIndex < 0 || rowIndex > t.maxRowNumber { + if rowIndex < 0 || rowIndex >= t.maxRowNumber { return fmt.Errorf("illegal argument rowIndex %d", rowIndex) } @@ -221,11 +221,11 @@ func (t *Tablet) GetMaxRowNumber() int { } func (t *Tablet) GetValueAt(columnIndex, rowIndex int) (interface{}, error) { - if columnIndex < 0 || columnIndex > len(t.measurementSchemas) { + if columnIndex < 0 || columnIndex >= len(t.measurementSchemas) { return nil, fmt.Errorf("illegal argument columnIndex %d", columnIndex) } - if rowIndex < 0 || rowIndex > t.maxRowNumber { + if rowIndex < 0 || rowIndex >= t.maxRowNumber { return nil, fmt.Errorf("illegal argument rowIndex %d", rowIndex) } diff --git a/client/tablet_test.go b/client/tablet_test.go index b19f34a..cd01d72 100644 --- a/client/tablet_test.go +++ b/client/tablet_test.go @@ -224,6 +224,22 @@ func TestTablet_SetValueAt(t *testing.T) { rowIndex: 0, }, wantErr: true, + }, { + name: "columnIndex-out-of-range-boundary", + args: args{ + value: 0, + columnIndex: 10, + rowIndex: 0, + }, + wantErr: true, + }, { + name: "rowIndex-out-of-range-boundary", + args: args{ + value: 0, + columnIndex: 0, + rowIndex: 1, + }, + wantErr: true, }, { name: "restart_count", args: args{ @@ -410,6 +426,20 @@ func TestTablet_GetValueAt(t *testing.T) { }, want: int64(1608268702780), wantErr: false, + }, { + name: "columnIndex-out-of-range-boundary", + args: args{ + columnIndex: 10, + rowIndex: 0, + }, + wantErr: true, + }, { + name: "rowIndex-out-of-range-boundary", + args: args{ + columnIndex: 0, + rowIndex: 1, + }, + wantErr: true, }, } if tablet, err := createTablet(1); err == nil {