Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
* [BUGFIX] Ring: Fix DynamoDB KV CAS not retrying on transactional conditional check failures. `TransactWriteItems` reports condition failures as `TransactionCanceledException` with a `ConditionalCheckFailed` cancellation reason, which was not recognized as retryable, so any concurrent ring update conflict (e.g. many ingesters joining during a rolling update) failed immediately instead of re-reading and retrying. `TransactionConflict` cancellation reasons are also treated as retryable. #7706
* [BUGFIX] Distributor: Return HTTP 499 (Client Closed Request) instead of 500 when a remote-write or OTLP push is canceled by the client, so client-side cancellations are no longer counted as server-side errors. #7717
* [BUGFIX] Querier: Fix gRPC `codes.Canceled` errors being mapped to HTTP 500 instead of 499 when a client cancels a query. #7738
* [BUGFIX] Querier: Fix panic (`index out of range [-1]`) in the active request tracker when truncating a `match[]`/`query` value made entirely of invalid UTF-8 continuation bytes. The backwards scan for a rune boundary now stops at index 0 instead of underflowing. #7729

## 1.21.1 2026-06-04

Expand Down
2 changes: 1 addition & 1 deletion pkg/util/request_tracker/request_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func trimStringByBytes(str string, size int) string {
bytesStr := []byte(str)
trimIndex := len(bytesStr)
if size < len(bytesStr) {
for !utf8.RuneStart(bytesStr[size]) {
for size > 0 && !utf8.RuneStart(bytesStr[size]) {
size--
}
trimIndex = size
Expand Down
14 changes: 14 additions & 0 deletions pkg/util/request_tracker/request_tracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ func TestTrimForJsonMarshalMultiByteUTF8(t *testing.T) {
}
}

// TestTrimForJsonMarshalInvalidUTF8 reproduces a panic where a string made
// entirely of UTF-8 continuation bytes (0x80-0xBF, no valid rune-start byte)
// caused the backwards scan for a rune boundary to underflow past index 0
// and index the byte slice with a negative index.
func TestTrimForJsonMarshalInvalidUTF8(t *testing.T) {
invalid := strings.Repeat("\x80", 1200)

require.NotPanics(t, func() {
out := trimForJsonMarshal(invalid, 800)
assert.True(t, utf8.ValidString(out), "result should be valid UTF-8")
assert.Equal(t, "", out)
})
}

// TestGenerateJSONEntryWithTruncatedFieldNegativeSize reproduces the request
// tracker panic where a multi-byte UTF-8 field had to be truncated to a
// negative remaining size because the rest of the entry already consumed the
Expand Down
Loading