Skip to content

fix out-of-range getbits width in legacy get_old_word1#240

Open
aizu-m wants to merge 1 commit into
dbry:masterfrom
aizu-m:get-old-word1-getbits-width
Open

fix out-of-range getbits width in legacy get_old_word1#240
aizu-m wants to merge 1 commit into
dbry:masterfrom
aizu-m:get-old-word1-getbits-width

Conversation

@aizu-m
Copy link
Copy Markdown
Contributor

@aizu-m aizu-m commented Jun 8, 2026

UBSan (clang -fsanitize=undefined), decoding a crafted version-3 file:

src/unpack3.c:1371:5: runtime error: shift exponent 35 is too large for 32-bit type 'uint32_t'
    #0 get_old_word1 unpack3.c:1371
    #1 unpack_samples3 unpack3.c:372

Was checking over the other legacy readers after the get_word3 fix. get_old_word1 pulls the entropy width k out of w1.k_value[chan] and passes it to getbits() before checking it. The (k & ~31) guard sits below the getbits call, folded into the bc==32 test, so an out-of-range width gets used first and rejected after.

On the first sample guess_k is 0, so a bitstream that opens with roughly 48 or more 1-bits drives k_value up to 32..47 (or wraps it negative). getbits then shifts the 32-bit register left by >= 32 while refilling. Behaviour is undefined. Reached through WavpackUnpackSamples on a version-3 lossless mono high (not new-high) file, so it only builds with --enable-legacy.

get_word1, get_word2, get_word3 and get_word4 all range-check the width before getbits. get_old_word1 is the odd one out. Moving its check ahead of the getbits call brings it in line and returns WORD_EOF on a bad width.

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