Skip to content

audio: copier: avoid shift by 32 in ALH nibble channel map - #11256

Open
tmleman wants to merge 1 commit into
thesofproject:mainfrom
tmleman:topic/upstream/pr/audio/dai/copier/fix_ub_on_int_shift
Open

tmleman wants to merge 1 commit into
thesofproject:mainfrom
tmleman:topic/upstream/pr/audio/dai/copier/fix_ub_on_int_shift

Conversation

@tmleman

@tmleman tmleman commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

bitmask_to_nibble_channel_map() fills the nibbles of absent channels with 0xf using 0xFFFFFFFF << (channel_count * 4). channel_mask comes from the host-supplied ALH multi-gateway blob and popcount() == 8 is accepted by copier_set_alh_multi_gtw_channel_map(), so a mask of 0xff makes the shift count 32, which is undefined behaviour for a 32-bit type (UBSan: "shift exponent 32 is too large for 32-bit type").

Xtensa and x86 mask the shift count to 5 bits, so the shift by 32 behaves as a shift by 0 and the map becomes 0xFFFFFFFF: every channel of an 8-channel ALH aggregation is then marked absent in copier_dai_params() instead of getting the identity map 0x76543210.

Only fill absent nibbles when there are fewer than 8 channels and use an unsigned literal. Results for all masks with fewer than 8 channels are unchanged.

Found by the IPC4 libFuzzer campaign with -fsanitize=undefined.

Copilot AI balanced review requested due to automatic review settings October 2, 2026 09:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The guard fixes the undefined shift while preserving behavior for smaller channel masks.

Review effort: Balanced
Findings: None

What changed in this PR

Prevents undefined 32-bit shifts when generating eight-channel ALH channel maps.

Changes:

  • Skips absent-channel filling when all eight channels are present.
  • Documents the avoided undefined behavior.
File Description
src/​audio/​copier/​copier_dai.c Safely generates the eight-channel identity map.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

nibble_map |= 0xFFFFFFFF << (channel_count * 4);
/* Absent channel is represented as 0xf nibble. With all 8 channels present the shift count
* would be 32, which is undefined behavior for 32-bit types.
* On Xtensa and x86 architectures this would result in returning 0xffffffff, marking all

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be shortened

bitmask_to_nibble_channel_map() fills the nibbles of absent channels
with 0xf using 0xFFFFFFFF << (channel_count * 4). channel_mask comes
from the host-supplied ALH multi-gateway blob and popcount() == 8 is
accepted by copier_set_alh_multi_gtw_channel_map(), so a mask of 0xff
makes the shift count 32, which is undefined behaviour for a 32-bit type
(UBSan: "shift exponent 32 is too large for 32-bit type").

Xtensa and x86 mask the shift count to 5 bits, so the shift by 32
behaves as a shift by 0 and the map becomes 0xFFFFFFFF: every channel of
an 8-channel ALH aggregation is then marked absent in
copier_dai_params() instead of getting the identity map 0x76543210.

Only fill absent nibbles when there are fewer than 8 channels and use an
unsigned literal. Results for all masks with fewer than 8 channels are
unchanged.

Found by the IPC4 libFuzzer campaign with -fsanitize=undefined.

Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
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.

3 participants