diff options
| author | Pedro Nascimento <pnascimento@gmail.com> | 2026-08-09 15:36:33 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-09 18:36:33 +0000 |
| commit | 4e39d06accfa65fbed9e034c3cd7face91a6d80c (patch) | |
| tree | 0bf4ee8560558d87a1972ea4dcd6627e68c853b2 /soh/include | |
| parent | 490e13616ed1205c34ac2ac3a8f1342495206f39 (diff) | |
fix(audio): bound audio-heap cache tables (SIGSEGV with large custom music packs) (#6932)
Root cause of three identical field crashes (audio thread, opcode fetch
through a pointer with its low 32 bits overwritten, seconds after scene
transitions): AudioHeap_AllocPermanent writes permanentCache[index] with
index = permanentPool.count and no bound against the 32-entry array. In
SoH every soundfont sync-load is forced permanent, and custom sequences
whose SEQ.xml says CachePolicy="Temporary" ALSO allocate permanently
(the factory stores the LUS enum where CACHE_TEMPORARY == 0, while
AudioLoad_SyncLoad's switch reads 0 with the ROM convention
'permanent'). A pack with ~60 streamed customs plus vanilla fonts pushes
count past 32 within a session, after which each allocation sprays a
{ptr, size, tableType/id} triplet at 24-byte stride through
gAudioContext - entry[135]'s ptr field lands exactly on
seqPlayers[0].scriptState.pc and entry[156] on seqPlayers[1]'s (both
verified against the crash-dump registers).
- permanentCache raised 32 -> 512 (12 KB) and AllocPermanent refuses
allocations past the array instead of corrupting memory.
- Same unbounded-index disease fixed in the three sibling writers:
AllocCached's persistent path (16-entry array; CACHE_EITHER degrades
to temporary, hard persistent requests fail cleanly),
AllocPersistentSampleCacheEntry, AllocTemporarySampleCacheEntry.
- seqLoadStatus malloc sized for the full id space (sequenceMapSize +
0xF) matching sequenceMap; custom ids above sequenceMapSize previously
overflowed the allocation by up to 15 bytes.
Upstream SoH bugs, not branch-introduced - this branch's many-track
packs merely made the overflow reachable in normal play. Standalone
upstreamable fix.
Diffstat (limited to 'soh/include')
| -rw-r--r-- | soh/include/z64audio.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index 42328cd8e..6fed61399 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -915,7 +915,8 @@ typedef struct { /* 0x2B30 */ AudioCache fontCache; /* 0x2C40 */ AudioCache sampleBankCache; /* 0x2D50 */ AudioAllocPool permanentPool; - /* 0x2D60 */ AudioCacheEntry permanentCache[32]; + // SOH [Bugfix] 32 -> 512: large custom-music packs overflowed this (see AudioHeap_AllocPermanent). + /* 0x2D60 */ AudioCacheEntry permanentCache[512]; /* 0x2EE0 */ AudioSampleCache persistentSampleCache; /* 0x3174 */ AudioSampleCache temporarySampleCache; /* 0x3408 */ AudioPoolSplit4 sessionPoolSplit; |
