Skip to content

[openal] Fix AL_SAMPLE_OFFSET and AL_BYTE_OFFSET with buffer 0 - #27420

Open
sbc100 wants to merge 1 commit into
emscripten-core:mainfrom
sbc100:openal_bufid_fix
Open

[openal] Fix AL_SAMPLE_OFFSET and AL_BYTE_OFFSET with buffer 0#27420
sbc100 wants to merge 1 commit into
emscripten-core:mainfrom
sbc100:openal_bufid_fix

Conversation

@sbc100

@sbc100 sbc100 commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

When AL_SAMPLE_OFFSET or AL_BYTE_OFFSET is set on a source, the library looks up the format of the queued audio data to convert the offset into seconds for sourceSeek.

Previously, this iteration used for (var bufId in src.bufQueue) and checked if (bufId). Because for..in iterates over array index strings ("0", "1", etc.), bufId received "0" on the first iteration. In JavaScript, non-empty strings are truthy, so if (bufId) evaluated if ("0"), which is always true.

As a result, the loop never skipped index 0. If src.bufQueue[0] happened to be the default placeholder dummy zero buffer (which has frequency: 0), it would read frequency = 0 and cause a division by zero (value /= 0), failing range validation with AL_INVALID_VALUE.

This change replaces both loops in src/lib/libopenal.js with for (var buf of src.bufQueue) and checks if (buf.id !== 0). A new test case is added to test/openal/test_openal_error.c to verify this behavior.

The original bug was introduced in fcf8d12.

It seems that there was an attempt to fix this in #10466 but I think this code always yield true both before and after this change because "0" string is truthy.

When `AL_SAMPLE_OFFSET` or `AL_BYTE_OFFSET` is set on a source, the
library looks up the format of the queued audio data to convert the
offset into seconds for `sourceSeek`.

Previously, this iteration used `for (var bufId in src.bufQueue)` and
checked `if (bufId)`. Because `for..in` iterates over array index
strings (`"0"`, `"1"`, etc.), `bufId` received `"0"` on the first
iteration. In JavaScript, non-empty strings are truthy, so `if (bufId)`
evaluated `if ("0")`, which is always true.

As a result, the loop never skipped index 0. If `src.bufQueue[0]`
happened to be the default placeholder dummy zero buffer (which has
`frequency: 0`), it would read `frequency = 0` and cause a division by
zero (`value /= 0`), failing range validation with `AL_INVALID_VALUE`.

This change replaces both loops in `src/lib/libopenal.js` with
`for (var buf of src.bufQueue)` and checks `if (buf.id !== 0)`. A new
test case is added to `test/openal/test_openal_error.c` to verify this
behavior.
@sbc100
sbc100 requested a review from kripken July 27, 2026 16:59
@sbc100
sbc100 requested a review from juj July 27, 2026 17:07
@sbc100

sbc100 commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator Author

CC @jpernst who wrote this code originally in fcf8d12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant