mirror of
https://github.com/prometheus/prometheus.git
synced 2026-02-03 20:39:32 -05:00
fix(promql): prevent panic in trimStringByBytes on invalid UTF-8
Add bounds check to prevent index out of range panic when trimStringByBytes receives a string containing only UTF-8 continuation bytes (0x80-0xBF). Previously, the loop would decrement size below 0 when no valid rune start byte was found, causing a panic. A malicious query string with only continuation bytes could crash the Prometheus server via the ActiveQueryTracker before the query was parsed or validated. Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
parent
bec70227f1
commit
65f8482335
2 changed files with 42 additions and 1 deletions
|
|
@ -164,7 +164,7 @@ func trimStringByBytes(str string, size int) string {
|
|||
|
||||
trimIndex := len(bytesStr)
|
||||
if size < len(bytesStr) {
|
||||
for !utf8.RuneStart(bytesStr[size]) {
|
||||
for size > 0 && !utf8.RuneStart(bytesStr[size]) {
|
||||
size--
|
||||
}
|
||||
trimIndex = size
|
||||
|
|
|
|||
|
|
@ -127,6 +127,47 @@ func TestMMapFile(t *testing.T) {
|
|||
require.Equal(t, []byte(data), bytes[:2], "Mmap failed")
|
||||
}
|
||||
|
||||
func TestTrimStringByBytes(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
input string
|
||||
size int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "normal ASCII string",
|
||||
input: "hello",
|
||||
size: 3,
|
||||
expected: "hel",
|
||||
},
|
||||
{
|
||||
name: "no trimming needed",
|
||||
input: "hi",
|
||||
size: 10,
|
||||
expected: "hi",
|
||||
},
|
||||
{
|
||||
name: "UTF-8 multibyte character boundary",
|
||||
input: "日本", // 6 bytes (3 bytes per character)
|
||||
size: 4,
|
||||
expected: "日", // trims back to complete character boundary
|
||||
},
|
||||
{
|
||||
name: "invalid UTF-8 continuation-only bytes",
|
||||
input: string([]byte{0x80, 0x81, 0x82, 0x83, 0x84}), // only continuation bytes
|
||||
size: 4,
|
||||
expected: "",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.NotPanics(t, func() {
|
||||
result := trimStringByBytes(tc.input, tc.size)
|
||||
require.Equal(t, tc.expected, result)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBrokenJSON(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
b []byte
|
||||
|
|
|
|||
Loading…
Reference in a new issue