Skip to content

fix: fix bug in query result marshaling for invalid utf8 characters - #14585

Merged
cstyan merged 3 commits into
mainfrom
callum-result-marshal-sanitize
Oct 28, 2024
Merged

fix: fix bug in query result marshaling for invalid utf8 characters#14585
cstyan merged 3 commits into
mainfrom
callum-result-marshal-sanitize

Conversation

@cstyan

@cstyan cstyan commented Oct 23, 2024

Copy link
Copy Markdown
Contributor

Potentially we want to fix this by actually sanitizing data for OTLP ingestion/structured metadata, but I think we should include a fix to allow users with data that is already stored in Loki to query it out.

The bug is present for streams which have structured metadata which contains invalid UTF-8 characters. When you write a query like {label="x"} there's no problem, but as soon as you do label="x"} |= "some filter" the bug kicks in because we pull in the structured metadata.

When we then go to marshal the labelset on the query result we run into an error here because the underlying call to NewLabelSet calls Prometheus' ParseMetric which enforces "any valid Unicode character" in the label value. This fails if there's an invalid character. I'm not entirely sure what the invalid character is or where it's coming from, but we have precedent for checking for it already as RuneError (here) in other places. For this PR I've simply copied what we do for the JSONParser from here.

…d utf8 characters are present

Signed-off-by: Callum Styan <callumstyan@gmail.com>
@cstyan
cstyan requested a review from a team as a code owner October 23, 2024 00:14
@cstyan cstyan changed the title [bug] fix bug in query result marshaling for invalid utf8 characters Oct 23, 2024
Signed-off-by: Callum Styan <callumstyan@gmail.com>

@vlad-diachenko vlad-diachenko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approving with small improvements to apply

Comment thread pkg/util/marshal/query.go Outdated
}
return r
}
stream.Labels = string(bytes.Map(removeInvalidUtf, []byte(stream.Labels)))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to use bytes.Map() only if []byte(stream.Labels) contains utf8.RuneError .
more details here

Comment thread pkg/util/marshal/query.go Outdated

for i, stream := range s {
// The rune error replacement is rejected by Prometheus hence replacing them with space.
removeInvalidUtf := func(r rune) rune {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be moved to global vars to initialize once

Labels: "{asdf=\"�\"}",
},
})
require.NoError(t, err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be useful to assert the result as well

Signed-off-by: Callum Styan <callumstyan@gmail.com>
@pull-request-size pull-request-size Bot added size/M and removed size/S labels Oct 25, 2024
@cstyan
cstyan merged commit f411a07 into main Oct 28, 2024
@cstyan
cstyan deleted the callum-result-marshal-sanitize branch October 28, 2024 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2 participants