← Our Research

ASI-2026-0005

tOS AAC Audio Decoder — Stack Overflow via Unclamped max_sfb

HIGH FIXED CVSS: 7.8 Published: 2026-07-20

Summary

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.

How We Found It

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.

Technical Detail

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.

Attack Scenario

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.

Root Cause

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.

Fix

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.

Affected Platforms

Artfical tOS < 0.9.109

Weakness Type

CWE-787, CWE-121, CWE-125

Discovered By

Artfical DT Developer Talha Berk Arslan

References