π Module Scanned
(automated audit scan)
π Summary
In the function of , when a looping voice reaches end-of-buffer, the cursor is reset to 0.0 and looping continues, but the bounds check that follows does not re-fetch the updated cursor value. Since was just modified to 0.0 before the comparison at line 265, the subsequent condition still uses the stale from before the reset. This means after looping, the first sample read can be at an incorrect offset, causing audio glitches or OOB memory access if the buffer was freed.
π Location
- File:
- Function/Scope: β loop cursor reset path
π΄ Severity: High
- Critical: Potential out-of-bounds memory read, possible crash or audio corruption
- High: Audio artifacts (clicking/popping) when looped sounds wrap
- Medium: The bug is masked by the subsequent re-calculation at line 275, but that second check can also trigger false positives when it shouldn't
π₯ Impact
When a looping voice reaches its end-of-buffer:
- is set to 0.0 at line 267
- The loop continues without breaking
- Line 265's bounds check uses stale (from before cursor reset)
- An incorrect sample offset may be used for the next iteration before re-calculation
- In pathological cases (e.g., very small buffers, or pitch > 1.0 causing rapid wrap), this could read past buffer end before the second check at line 276 catches it
π Evidence
The problem is that after , control flows directly to line 275 without a or break. The code continues to line 283 where it reads using the updated cursor (now 0), but the second bounds check at line 276 uses the newly calculated (which would be 0 after loop). If buffer length is less than 2 bytes (unlikely but possible for malformed data), the check at line 276 would catch it, but the deeper issue is the flow: after in the loop, the code continues to use (line 283) which was calculated before the reset.
π οΈ Proposed Fix
After setting inside the loop, add a to skip the rest of the iteration and allow the next iteration to properly calculate from the reset cursor:
Additionally, consolidate the redundant bounds checks. The check at line 276-279 duplicates logic that could be handled more cleanly after the cursor reset.
β
Acceptance Criteria
π References
π Module Scanned
(automated audit scan)
π Summary
In the function of , when a looping voice reaches end-of-buffer, the cursor is reset to 0.0 and looping continues, but the bounds check that follows does not re-fetch the updated cursor value. Since was just modified to 0.0 before the comparison at line 265, the subsequent condition still uses the stale from before the reset. This means after looping, the first sample read can be at an incorrect offset, causing audio glitches or OOB memory access if the buffer was freed.
π Location
π΄ Severity: High
π₯ Impact
When a looping voice reaches its end-of-buffer:
π Evidence
The problem is that after , control flows directly to line 275 without a or break. The code continues to line 283 where it reads using the updated cursor (now 0), but the second bounds check at line 276 uses the newly calculated (which would be 0 after loop). If buffer length is less than 2 bytes (unlikely but possible for malformed data), the check at line 276 would catch it, but the deeper issue is the flow: after in the loop, the code continues to use (line 283) which was calculated before the reset.
π οΈ Proposed Fix
After setting inside the loop, add a to skip the rest of the iteration and allow the next iteration to properly calculate from the reset cursor:
Additionally, consolidate the redundant bounds checks. The check at line 276-279 duplicates logic that could be handled more cleanly after the cursor reset.
β Acceptance Criteria
Compiler: 0.16.0
assets/shaders/vulkan/shadow.vert
assets/shaders/vulkan/lpv_propagate.comp
assets/shaders/vulkan/ui.frag
assets/shaders/vulkan/ui_tex.frag
assets/shaders/vulkan/g_pass.frag
assets/shaders/vulkan/debug_shadow.vert
assets/shaders/vulkan/lpv_inject.comp
assets/shaders/vulkan/ssao.vert
assets/shaders/vulkan/sky.frag
assets/shaders/vulkan/water.vert
assets/shaders/vulkan/bloom_downsample.vert
assets/shaders/vulkan/bloom_upsample.vert
assets/shaders/vulkan/debug_shadow.vert
assets/shaders/vulkan/fxaa.vert
assets/shaders/vulkan/post_process.vert
assets/shaders/vulkan/shadow.vert
assets/shaders/vulkan/sky.vert
assets/shaders/vulkan/ssao.vert
assets/shaders/vulkan/taa.vert
assets/shaders/vulkan/terrain.vert
assets/shaders/vulkan/ui.vert
assets/shaders/vulkan/ui_tex.vert
assets/shaders/vulkan/water.vert
assets/shaders/vulkan/bloom_downsample.frag
assets/shaders/vulkan/bloom_upsample.frag
assets/shaders/vulkan/debug_shadow.frag
assets/shaders/vulkan/fxaa.frag
assets/shaders/vulkan/g_pass.frag
assets/shaders/vulkan/post_process.frag
assets/shaders/vulkan/shadow.frag
assets/shaders/vulkan/sky.frag
assets/shaders/vulkan/ssao.frag
assets/shaders/vulkan/ssao_blur.frag
assets/shaders/vulkan/taa.frag
assets/shaders/vulkan/terrain.frag
assets/shaders/vulkan/terrain_debug.frag
assets/shaders/vulkan/ui.frag
assets/shaders/vulkan/ui_tex.frag
assets/shaders/vulkan/water.frag
assets/shaders/vulkan/culling.comp
assets/shaders/vulkan/depth_pyramid.comp
assets/shaders/vulkan/lpv_inject.comp
assets/shaders/vulkan/lpv_propagate.comp
assets/shaders/vulkan/mesh.comp
assets/shaders/vulkan/debug_shadow.frag
assets/shaders/vulkan/taa.frag
assets/shaders/vulkan/mesh.comp
assets/shaders/vulkan/water.frag
assets/shaders/vulkan/taa.vert
assets/shaders/vulkan/depth_pyramid.comp
assets/shaders/vulkan/culling.comp
assets/shaders/vulkan/ssao.frag
assets/shaders/vulkan/ui.vert
assets/shaders/vulkan/shadow.frag
assets/shaders/vulkan/ssao_blur.frag
assets/shaders/vulkan/terrain.vert
assets/shaders/vulkan/ui_tex.vert
assets/shaders/vulkan/terrain.frag
assets/shaders/vulkan/sky.vert
π References