Fix/string table oom on malformed apk#6
Merged
MiroslavDrbal merged 2 commits intomasterfrom Apr 10, 2026
Merged
Conversation
Two allocation vulnerabilities in string table parsing allow a crafted
resources.arsc to cause multi-GiB heap allocations:
parseStringTable — res.data = make([]byte, r.N)
r.N is derived from the chunk's totalLen field, a raw uint32 that a
malformed APK can set to ~4 GiB. make() commits the memory immediately;
io.ReadFull then fails (if the file is smaller), but only after the 4 GiB
block is live on the heap. The existing stringCnt >= 2M guard does not
bound the data section size. Guard with a 50 MiB limit before the make.
parseString16 — buf = make([]uint16, strCharacters)
The extended 31-bit length encoding (high bit of the first uint16 set)
allows strCharacters up to 0x7FFF_FFFF (4 GiB as []uint16) per call.
r is bytes.NewReader(t.data[offset:]), so binary.Read fails immediately
when the actual data is smaller -- but only after the allocation lands.
Fix with two guards in order:
1. Validate strCharacters against br.Len(): a correctly-formed string
cannot claim more chars than remaining_bytes/2. Catches both crafted
fields and any future decoding misalignment.
2. Secondary cap at 64 KiB: no legitimate resource string exceeds this.
Also fix &buf -> buf in binary.Read calls (parseString16, parseString8):
Passing *[]uint16 / *[]uint8 instead of the slice value itself bypasses
binary.Read's intDataSize fast-path switch (which handles []uint16 /
[]uint8 but not pointer-to-slice). The fallback reflection path allocates
an extra []byte temp buffer of the same size and calls reflect.New per
element -- visible as ~3 GiB flat in encoding/binary.Read and ~378 MB
in reflect.New in heap profiles of affected servers. Passing the slice
directly uses the fast path, is functionally identical, and is zero-
reflection.
0911a35 to
86806db
Compare
Tasssadar
reviewed
Apr 9, 2026
Add hierarchical size validation to the binary resource parser. Every size field parsed from the file is now validated against the bytes actually available from the parent before it can drive an allocation or loop. common.go: - parseChunkHeader enforces headerLen >= chunkHeaderSize and totalLen >= headerLen, rejecting structurally invalid chunks. binxml.go: - ParseXml: replaced uint32 totalLen subtraction with int64 dataLen to eliminate underflow that could create ~4 GiB loop bounds. Loop position tracking changed to int64. Inner chunks validated against remaining parent data. Magic 2*4 replaced with chunkHeaderSize constant. - parseResourceIds: capped at 1M entries (~4 MB). resources.go: - ParseResourceTable: same int64 arithmetic and inner chunk bounds check as ParseXml. - parseTypeSpec: signature tightened to *io.LimitedReader, entryCount validated against r.N before the append loop. stringtable.go: - parseStringTable: 4*stringCnt validated against r.N before allocating the string offsets buffer. - parseStringTableWithChunk: uint32 subtraction moved to int64 space.
86806db to
997da5a
Compare
Tasssadar
approved these changes
Apr 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.