fix memory corruption in labels when scraping with protbuf

Signed-off-by: Piotr <17101802+thampiotr@users.noreply.github.com>
This commit is contained in:
Piotr 2025-07-29 17:29:40 +01:00
parent 0b3ed4020c
commit be46837c12
2 changed files with 11 additions and 8 deletions

View File

@ -40,8 +40,7 @@ jobs:
- uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
- uses: ./.github/promci/actions/setup_environment
- run: go test --tags=dedupelabels ./...
- run: go test --tags=slicelabels -race ./cmd/prometheus
- run: go test --tags=slicelabels -race ./prompb/io/prometheus/client
- run: go test --tags=slicelabels -race ./cmd/prometheus ./prompb/io/prometheus/client
- run: go test --tags=forcedirectio -race ./tsdb/
- run: GOARCH=386 go test ./...
- uses: ./.github/promci/actions/check_proto

View File

@ -62,6 +62,9 @@ func NewMetricStreamingDecoder(data []byte) *MetricStreamingDecoder {
var errInvalidVarint = errors.New("clientpb: invalid varint encountered")
// NextMetricFamily decodes the next metric family from the input without metrics.
// Use NextMetric() to decode metrics. The MetricFamily fields Name, Help and Unit
// are only valid until NextMetricFamily is called again.
func (m *MetricStreamingDecoder) NextMetricFamily() error {
b := m.in[m.inPos:]
if len(b) == 0 {
@ -153,6 +156,7 @@ func (m *MetricStreamingDecoder) GetLabel() {
type scratchBuilder interface {
Add(name, value string)
UnsafeAddBytes(name, value []byte)
}
// Label parses labels into labels scratch builder. Metric name is missing
@ -170,9 +174,9 @@ func (m *MetricStreamingDecoder) Label(b scratchBuilder) error {
}
// parseLabel is essentially LabelPair.Unmarshal but directly adding into scratch builder
// and reusing strings.
// via UnsafeAddBytes method to reuse strings.
func parseLabel(dAtA []byte, b scratchBuilder) error {
var name, value string
var name, value []byte
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@ -231,7 +235,7 @@ func parseLabel(dAtA []byte, b scratchBuilder) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
name = yoloString(dAtA[iNdEx:postIndex])
name = dAtA[iNdEx:postIndex]
if !model.LabelName(name).IsValid() {
return fmt.Errorf("invalid label name: %s", name)
}
@ -266,8 +270,8 @@ func parseLabel(dAtA []byte, b scratchBuilder) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
value = yoloString(dAtA[iNdEx:postIndex])
if !utf8.ValidString(value) {
value = dAtA[iNdEx:postIndex]
if !utf8.ValidString(yoloString(value)) {
return fmt.Errorf("invalid label value: %s", value)
}
iNdEx = postIndex
@ -289,7 +293,7 @@ func parseLabel(dAtA []byte, b scratchBuilder) error {
if iNdEx > l {
return io.ErrUnexpectedEOF
}
b.Add(name, value)
b.UnsafeAddBytes(name, value)
return nil
}