Skip to content

Commit b272bf3

Browse files
committed
copier: fix NULL converter crash for non-zero sink_queue_id
Fix NULL pointer dereference in copier when sink buffer IDs map to non-zero sink_queue_id values but converters are not initialized. The issue occurs when IPC4_SINK_QUEUE_ID(buf_get_id(sink)) extracts a non-zero queue ID from a sink buffer's ID, but copier_prepare() only initializes converter[0]. This causes crashes in do_conversion_copy() when accessing cd->converter[i] for i != 0. This can happen even in single sink scenarios where the buffer ID encoding results in sink_queue_id=1 instead of the expected 0. The fix enhances copier_prepare() to: - Iterate through all connected sink buffers - Extract the actual sink_queue_id for each buffer - Initialize converters for the queue IDs that are actually used - Skip redundant initialization if converter already exists - Provide proper error handling for out-of-range queue IDs Resolves crashes in topologies where single sink copiers have buffers with non-zero queue ID mappings. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
1 parent 4d898ff commit b272bf3

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

src/audio/copier/copier.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,17 +344,47 @@ static int copier_prepare(struct processing_module *mod,
344344
}
345345

346346
if (!cd->endpoint_num) {
347+
struct comp_buffer *sink;
348+
347349
/* set up format conversion function for pin 0, for other pins (if any)
348350
* format is set in IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT handler
349351
*/
350352
cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt,
351-
&cd->config.out_fmt, ipc4_gtw_none,
352-
ipc4_bidirection, DUMMY_CHMAP);
353+
&cd->config.out_fmt, ipc4_gtw_none,
354+
ipc4_bidirection, DUMMY_CHMAP);
353355
if (!cd->converter[0]) {
354356
comp_err(dev, "can't support for in format %d, out format %d",
355357
cd->config.base.audio_fmt.depth, cd->config.out_fmt.depth);
356358
return -EINVAL;
357359
}
360+
361+
/* Initialize converters for all connected sink buffers.
362+
* Buffer ID to sink_queue_id mapping may result in non-zero queue IDs
363+
* even for single sink scenarios, so we need converters for actual IDs used.
364+
*/
365+
comp_dev_for_each_consumer(dev, sink) {
366+
int sink_queue_id = IPC4_SINK_QUEUE_ID(buf_get_id(sink));
367+
368+
if (sink_queue_id >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) {
369+
comp_err(dev, "sink_queue_id %d out of range", sink_queue_id);
370+
return -EINVAL;
371+
}
372+
373+
/* Skip if converter already initialized (e.g., pin 0 above) */
374+
if (cd->converter[sink_queue_id])
375+
continue;
376+
377+
cd->converter[sink_queue_id] =
378+
get_converter_func(&cd->config.base.audio_fmt,
379+
&cd->config.out_fmt,
380+
ipc4_gtw_none,
381+
ipc4_bidirection, DUMMY_CHMAP);
382+
if (!cd->converter[sink_queue_id]) {
383+
comp_err(dev, "can't get converter for sink_queue_id %d",
384+
sink_queue_id);
385+
return -EINVAL;
386+
}
387+
}
358388
}
359389

360390
return 0;

0 commit comments

Comments
 (0)