Skip to content

fix left shift of negative width in legacy get_word3/get_old_word1#245

Open
aizu-m wants to merge 1 commit into
dbry:masterfrom
aizu-m:legacy-width-leftshift-negative
Open

fix left shift of negative width in legacy get_word3/get_old_word1#245
aizu-m wants to merge 1 commit into
dbry:masterfrom
aizu-m:legacy-width-leftshift-negative

Conversation

@aizu-m

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

Copy link
Copy Markdown
Contributor

Turned this up building --enable-legacy under -fsanitize=undefined and decoding mutated version-3 files.

  1. get_word3 forms dbits from the bitstream as (ave_dbits>>8) + 1 + delta_dbits, then does ave_dbits[chan] += dbits << 3 before the dbits < 0 guard, so a long run of leading 1-bits leaves dbits negative when it is shifted.
  2. get_old_word1 shifts k_value into ave_k the same way, before k_value is range checked.

UBSan reports "left shift of negative value -40" at the get_word3 update on a crafted lossy mono file. The shifted result is only consumed on the error path, so output for valid files is unchanged. Cast the operand to uint32_t before the shift, matching the min_value/max_value shifts already in unpack_samples3. Added a regression file under fuzzing/regression/.

get_word3 and get_old_word1 update their running bit-width averages with value << 3 before the width is range checked, so a crafted version-3 stream can shift a negative dbits/k_value, which is undefined. Cast to uint32_t before the shift, as the min_value/max_value shifts in unpack_samples3 already do.
@dbry

dbry commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Thanks for this, but I think a cleaner fix would be to replace the left-shift of 3 with a multiply by 8. It's not ugly like the cast and optimizing compilers are going to generate the same code anyway. What do you think?

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.

2 participants