Skip to content

Fix pprof validation: nil period_type and off-by-one string-table bounds#6376

Merged
brancz merged 1 commit into
parca-dev:mainfrom
arpitjain099:chore/validate-pprof-bounds
Jul 20, 2026
Merged

Fix pprof validation: nil period_type and off-by-one string-table bounds#6376
brancz merged 1 commit into
parca-dev:mainfrom
arpitjain099:chore/validate-pprof-bounds

Conversation

@arpitjain099

Copy link
Copy Markdown
Contributor

While reading the pprof ingest path I hit two panics in ValidatePprofProfile (pkg/normalizer/validate.go). This validator runs on the WriteRaw gRPC ingest that every agent uses to push profiles, so the profile bytes are attacker-influenced, and both cases crash the validator (or the code just past it) rather than returning an error.

The first is a nil pointer deref. period_type is optional, so a profile that omits it arrives with a nil PeriodType. The rest of the function nil-checks its pointer fields, but the period_type branch dereferences p.PeriodType.Type directly, so merely leaving the field out panics inside the validator. I wrapped those two checks in a nil guard like everything else.

The second is an off-by-one in the string-table bounds checks. They use > len(StringTable), but string indices are 0-based, so the valid range is 0..len-1. An index exactly equal to len slips through the check and is one past the end, and downstream code (MetaFromPprof, LabelsFromSample) then indexes it and panics with index out of range. I changed the eleven 0-based string-index checks to >=. I left the mapping/function/location id checks as > on purpose, since those ids are 1-based and len is a valid id.

Added a table-driven test in the normalizer package: an omitted period_type, and an index equal to the string-table length on both the sample-type and period-type paths, plus a valid control. The bad cases panic (or are wrongly accepted) before the change and return a clean error or validate fine after it. go test ./pkg/normalizer/... passes.

Happy to sign the CLA. Let me know if you would rather split the two fixes or send this against a release branch.

ValidatePprofProfile runs on the WriteRaw ingest path, so it sees
attacker-influenced pprof bytes. Two crashes are reachable there.

First, period_type is an optional field and comes across as a nil
*ValueType when omitted. Every other pointer in the validator is
nil-checked, but the period_type branch dereferences p.PeriodType
directly, so a profile that simply leaves it out panics inside the
validator. Guard it like the rest.

Second, the string-table index checks use > len(StringTable). String
indices are 0-based, so the only valid values are 0..len-1 and an index
equal to len passes the check but is one past the end. Downstream code
(MetaFromPprof, LabelsFromSample) then indexes it and panics. Switch the
eleven 0-based string-index checks to >=. The 1-based id checks
(mapping/function/location) are left as > since len is a valid id there.

Adds a table-driven test covering an omitted period_type and an index
equal to the string-table length for both the sample-type and
period-type paths.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099
arpitjain099 requested a review from a team as a code owner July 19, 2026 17:35
@CLAassistant

CLAassistant commented Jul 19, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@brancz

brancz commented Jul 20, 2026

Copy link
Copy Markdown
Member

Thank you very much!

@brancz
brancz merged commit 2bc9f11 into parca-dev:main Jul 20, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants