From 12fb59a80eea0cd68a447417c002a27f5f47fa4a Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 13:08:12 +0100 Subject: [PATCH] pcm_converter: reject out-of-range channel map at runtime The remap routines validated the source channel nibble only with an assert, which is compiled out in release builds. Fold the bound into the existing mute path so an out-of-range nibble mutes the output instead of indexing past the source frame. Signed-off-by: Liam Girdwood --- src/audio/pcm_converter/pcm_remap.c | 35 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/audio/pcm_converter/pcm_remap.c b/src/audio/pcm_converter/pcm_remap.c index 9204b21ee8ab..f0ad6912a5f8 100644 --- a/src/audio/pcm_converter/pcm_remap.c +++ b/src/audio/pcm_converter/pcm_remap.c @@ -68,13 +68,14 @@ static int remap_c16(const struct audio_stream *source, uint32_t dummy1, src_channel = chmap & 0xf; chmap >>= 4; - if (src_channel == 0xf) { + /* 0xf means "mute"; also mute any out-of-range source channel so + * a crafted chmap nibble cannot index past the source frame. + */ + if (src_channel == 0xf || src_channel >= num_src_channels) { mute_channel_c16(sink, sink_channel, frames); continue; } - assert(src_channel < num_src_channels); - src = (int16_t *)audio_stream_get_rptr(source) + src_channel; dst = (int16_t *)audio_stream_get_wptr(sink) + sink_channel; @@ -126,13 +127,14 @@ static inline int remap_c32_left_shift(const struct audio_stream *source, src_channel = chmap & 0xf; chmap >>= 4; - if (src_channel == 0xf) { + /* 0xf means "mute"; also mute any out-of-range source channel so + * a crafted chmap nibble cannot index past the source frame. + */ + if (src_channel == 0xf || src_channel >= num_src_channels) { mute_channel_c32(sink, sink_channel, frames); continue; } - assert(src_channel < num_src_channels); - src = (int32_t *)audio_stream_get_rptr(source) + src_channel; dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; @@ -184,13 +186,14 @@ static inline int remap_c32_right_shift(const struct audio_stream *source, src_channel = chmap & 0xf; chmap >>= 4; - if (src_channel == 0xf) { + /* 0xf means "mute"; also mute any out-of-range source channel so + * a crafted chmap nibble cannot index past the source frame. + */ + if (src_channel == 0xf || src_channel >= num_src_channels) { mute_channel_c32(sink, sink_channel, frames); continue; } - assert(src_channel < num_src_channels); - src = (int32_t *)audio_stream_get_rptr(source) + src_channel; dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; @@ -243,13 +246,14 @@ static inline int remap_c16_to_c32(const struct audio_stream *source, src_channel = chmap & 0xf; chmap >>= 4; - if (src_channel == 0xf) { + /* 0xf means "mute"; also mute any out-of-range source channel so + * a crafted chmap nibble cannot index past the source frame. + */ + if (src_channel == 0xf || src_channel >= num_src_channels) { mute_channel_c32(sink, sink_channel, frames); continue; } - assert(src_channel < num_src_channels); - src = (int16_t *)audio_stream_get_rptr(source) + src_channel; dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; @@ -302,13 +306,14 @@ static inline int remap_c32_to_c16(const struct audio_stream *source, src_channel = chmap & 0xf; chmap >>= 4; - if (src_channel == 0xf) { + /* 0xf means "mute"; also mute any out-of-range source channel so + * a crafted chmap nibble cannot index past the source frame. + */ + if (src_channel == 0xf || src_channel >= num_src_channels) { mute_channel_c16(sink, sink_channel, frames); continue; } - assert(src_channel < num_src_channels); - src = (int32_t *)audio_stream_get_rptr(source) + src_channel; dst = (int16_t *)audio_stream_get_wptr(sink) + sink_channel;