mirror of
https://github.com/prometheus/prometheus.git
synced 2026-02-03 20:39:32 -05:00
parser: fix panic when label exceeds 16MB
Signed-off-by: Meher Assel <asselmeher@gmail.com>
This commit is contained in:
parent
44d772b4e7
commit
5b6048a755
3 changed files with 38 additions and 5 deletions
|
|
@ -16,6 +16,7 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
|
@ -540,13 +541,16 @@ func marshalLabelToSizedBuffer(m *Label, data []byte) int {
|
|||
return len(data) - i
|
||||
}
|
||||
|
||||
// ErrLabelTooLong is returned when a label name or value exceeds the maximum allowed size.
|
||||
var ErrLabelTooLong = errors.New("string too long to encode as label")
|
||||
|
||||
func sizeWhenEncoded(x uint64) (n int) {
|
||||
if x < 255 {
|
||||
return 1
|
||||
} else if x <= 1<<24 {
|
||||
return 4
|
||||
}
|
||||
panic("String too long to encode as label.")
|
||||
panic(ErrLabelTooLong)
|
||||
}
|
||||
|
||||
func encodeSize(data []byte, offset, v int) int {
|
||||
|
|
|
|||
|
|
@ -340,16 +340,23 @@ var errUnexpected = errors.New("unexpected error")
|
|||
// recover is the handler that turns panics into returns from the top level of Parse.
|
||||
func (*parser) recover(errp *error) {
|
||||
e := recover()
|
||||
switch _, ok := e.(runtime.Error); {
|
||||
case ok:
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch err := e.(type) {
|
||||
case runtime.Error:
|
||||
// Print the stack trace but do not inhibit the running application.
|
||||
buf := make([]byte, 64<<10)
|
||||
buf = buf[:runtime.Stack(buf, false)]
|
||||
|
||||
fmt.Fprintf(os.Stderr, "parser panic: %v\n%s", e, buf)
|
||||
*errp = errUnexpected
|
||||
case e != nil:
|
||||
*errp = e.(error)
|
||||
case error:
|
||||
*errp = err
|
||||
default:
|
||||
// Handle non-error panic values (e.g., strings) gracefully.
|
||||
*errp = fmt.Errorf("%v", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6004,6 +6004,28 @@ func TestRecoverParserError(t *testing.T) {
|
|||
panic(e)
|
||||
}
|
||||
|
||||
func TestRecoverParserString(t *testing.T) {
|
||||
p := NewParser("foo bar")
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "some string panic")
|
||||
}()
|
||||
defer p.recover(&err)
|
||||
|
||||
panic("some string panic")
|
||||
}
|
||||
|
||||
func TestParseLabelTooLong(t *testing.T) {
|
||||
const maxLabelSize = 1 << 24
|
||||
longValue := strings.Repeat("a", maxLabelSize+1)
|
||||
input := `{job="` + longValue + `"}`
|
||||
|
||||
_, err := ParseMetric(input)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestExtractSelectors(t *testing.T) {
|
||||
for _, tc := range [...]struct {
|
||||
input string
|
||||
|
|
|
|||
Loading…
Reference in a new issue