tOS AAC Audio Decoder — Stack Overflow via Unclamped max_sfb
In decode_ics of aac_decoder.c, the max_sfb field is read directly from the AAC bitstream as an unvalidated 6-bit value (0-63) and used as a loop bound when populating the sfb_top and sf_val stack arrays, which are only sized for AAC_MAX_SFB (51) entries. A crafted AAC frame with max_sfb greater than 51 causes both stack arrays to be written past their bounds, and also causes an out-of-bounds read of the static sfb44 lookup table. This is reachable by decoding any attacker-supplied .m4a or .aac audio file through the media player.
After finding the overflow issue in the PNG parser in ASI-2026-0004, we decided to audit kernel/audio for a similar lack of bounds checking in the audio decoders. While reviewing decode_ics in aac_decoder.c, we found that the max_sfb field, once read from the bitstream, was used directly as a loop bound with no upper clamp at all.
max_sfb is read from the AAC bitstream as an unvalidated 6-bit value (0-63) and used as the loop bound when populating the sfb_top and sf_val stack arrays. These arrays are only sized for AAC_MAX_SFB (51) entries. Notably, section_data's own write loop already correctly clamps max_sfb against AAC_MAX_SFB — but that clamp was never propagated to the two downstream loops that populate sfb_top and sf_val. A max_sfb greater than 51 causes both stack arrays to be written past their bounds, and also causes an out-of-bounds read of the static sfb44 lookup table.
An attacker crafts a malicious .m4a or .aac file containing a raw_data_block with max_sfb set above 51 (up to 63). When the victim attempts to play this file through the media player, decode_ics writes past the bounds of both the sfb_top and sf_val stack arrays and reads out of bounds from the sfb44 lookup table. Overwriting adjacent stack values — potentially including return addresses — makes this a serious issue with the potential to escalate to code execution.
max_sfb is parsed straight from the bitstream and used unclamped as the bound for the sfb_top[] and sf_val[] loops, even though section_data's own write loop already correctly clamps against AAC_MAX_SFB — the two downstream loops did not inherit that same bound. The clamp existed in exactly one place instead of being enforced everywhere the value was used.
max_sfb is now clamped to AAC_MAX_SFB immediately after being read from the bitstream, so every loop keyed off it stays within the bounds of both stack arrays and the sfb44 lookup table.
CWE-787, CWE-121, CWE-125
Artfical DT Developer Talha Berk Arslan