component: avoid pre-allocating untrusted lengths in the binary set readers - #3091
component: avoid pre-allocating untrusted lengths in the binary set readers#3091AlexandrKhromov2005 wants to merge 2 commits into
Conversation
…eaders ReadDomainSetBin and ReadIpCidrSet read a length with binary.Read and then immediately allocate a slice of that size (make([]uint64, length) / make([]byte, length) / make([]netipx.IPRange, length)) before reading the elements. The length is only checked for < 1, not for an upper bound, so a crafted binary set (reached from an .mrs rule-set, including remote rule-providers) can declare a huge length and OOM the process on the allocation or panic with "makeslice: len out of range". Read incrementally instead: element slices grow via append with a capped initial capacity; the byte slice is read through io.CopyN into a growable buffer. Add FuzzReadDomainSetBin / FuzzReadIpCidrSet.
…trusted length The .mrs reader read a reserved extra field via make([]byte, length) where length is an untrusted int64 checked only for < 0. A crafted rule-set could declare a huge length and abort the process (fatal runtime: out of memory, or a makeslice len-out-of-range panic) before any body is read. The extra bytes are currently unused, so discard them with io.CopyN, which streams and returns a short-read error for a bogus length. Adds a regression test.
|
While re-auditing the
extra := make([]byte, length) // length is an untrusted int64, only checked for < 0
_, err = io.ReadFull(reader, extra)
Added a regression test ( |
component: avoid pre-allocating untrusted lengths in the binary set readers
ReadDomainSetBin(component/trie) andReadIpCidrSet(component/cidr) read a length withbinary.Readand immediately allocate a slice of that size(
make([]uint64, length)/make([]byte, length)/make([]netipx.IPRange, length)) beforereading the elements. The length is only checked for
< 1, not for an upper bound, so a craftedbinary set — reachable from an
.mrsrule-set, including remote rule-providers(
rules/providerfetches provider content over HTTP and callsrulesMrsParse) — can declare ahuge length and either OOM the process on the allocation or panic with
makeslice: len out of range.Found by fuzzing (
go test -fuzz); the readers crash on a tiny input immediately.Fix
Read incrementally instead of trusting the length for a single allocation:
appendwith a capped initial capacity, so a bogus length hits EOFwhile reading the elements;
io.CopyNinto a growable buffer.Adds
FuzzReadDomainSetBin/FuzzReadIpCidrSet. Existing tests pass; valid sets still decode.