From 1f32181b79958d8aeda8dca04d877a6b55897dd8 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 6 May 2026 16:40:53 +0100 Subject: [PATCH 1/3] audio: asrc: Fix heap double-free during teardown Properly track allocation state in the ASRC component lifecycle to prevent double-free of heap memory during module teardown in ZTest environments. Signed-off-by: Liam Girdwood --- src/audio/asrc/asrc.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index e9c9e6e736d4..34776635da04 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -315,15 +315,25 @@ static void asrc_release_buffers(struct processing_module *mod, struct asrc_farr static int asrc_free(struct processing_module *mod) { struct comp_data *cd = module_get_private_data(mod); - struct comp_dev *dev = mod->dev; - comp_dbg(dev, "entry"); + comp_dbg(mod->dev, "entry"); + + if (!cd) + return 0; mod_free(mod, cd->buf); - asrc_release_buffers(mod, cd->asrc_obj); - asrc_free_polyphase_filter(mod, cd->asrc_obj); - mod_free(mod, cd->asrc_obj); + cd->buf = NULL; + + if (cd->asrc_obj) { + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + cd->asrc_obj = NULL; + } + mod_free(mod, cd); + module_set_private_data(mod, NULL); + return 0; } @@ -862,12 +872,17 @@ static int asrc_reset(struct processing_module *mod) asrc_dai_stop_timestamp(cd); /* Free the allocations those were done in prepare() */ - asrc_release_buffers(mod, cd->asrc_obj); - asrc_free_polyphase_filter(mod, cd->asrc_obj); - mod_free(mod, cd->asrc_obj); - mod_free(mod, cd->buf); - cd->asrc_obj = NULL; - cd->buf = NULL; + if (cd->asrc_obj) { + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + cd->asrc_obj = NULL; + } + + if (cd->buf) { + mod_free(mod, cd->buf); + cd->buf = NULL; + } return 0; } From 6adec5b005b3a7280c11b2dc1579b4f750a13444 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 6 May 2026 16:40:59 +0100 Subject: [PATCH 2/3] audio: mfcc: Add frame_shift validation to prevent division by zero Add input validation for the frame_shift configuration field in mfcc_setup(). A zero or negative value would cause a division by zero during STFT processing. Signed-off-by: Liam Girdwood --- src/audio/mfcc/mfcc_setup.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/audio/mfcc/mfcc_setup.c b/src/audio/mfcc/mfcc_setup.c index dded450673ad..9d662fb1d398 100644 --- a/src/audio/mfcc/mfcc_setup.c +++ b/src/audio/mfcc/mfcc_setup.c @@ -155,6 +155,14 @@ int mfcc_setup(struct processing_module *mod, int max_frames, int sample_rate, i state->emph.coef = -config->preemphasis_coefficient; /* Negate config parameter */ fft->fft_size = config->frame_length; fft->fft_padded_size = 1 << (31 - norm_int32(fft->fft_size)); /* Round up to nearest 2^N */ + /* frame_shift is the hop size and must be a positive value no larger + * than the frame/FFT length, otherwise prev_data_size below underflows + */ + if (config->frame_shift <= 0 || config->frame_shift > config->frame_length) { + comp_err(dev, "invalid frame_shift %d for frame_length %d", + config->frame_shift, config->frame_length); + return -EINVAL; + } fft->fft_hop_size = config->frame_shift; fft->half_fft_size = (fft->fft_padded_size >> 1) + 1; From 58d5b7d39069bd2832c9ab7ed029b6e27f1d1143 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 6 May 2026 16:41:04 +0100 Subject: [PATCH 3/3] audio: mic_privacy_manager: Fix NULL pointer dereference in ZTest Add null checks for hardware device pointers that may not be available when running in ZTest environments without real hardware. Signed-off-by: Liam Girdwood --- .../mic_privacy_manager/mic_privacy_manager_intel.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c index 5120c2ab4b59..764a35086622 100644 --- a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c +++ b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c @@ -95,6 +95,15 @@ int mic_privacy_manager_init(void) if (!mic_priv_dev) return -EINVAL; + if (!device_is_ready(mic_priv_dev)) { + LOG_ERR("mic_privacy device not ready"); + /* Clear the handle so later helpers take their !mic_priv_dev + * path instead of dereferencing a device that is not ready + */ + mic_priv_dev = NULL; + return -ENODEV; + } + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; mic_privacy_policy = mic_privacy_api->get_policy(); @@ -109,6 +118,9 @@ int mic_privacy_manager_init(void) int mic_privacy_manager_get_policy(void) { + if (!mic_priv_dev) + return MIC_PRIVACY_HW_MANAGED; + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; return mic_privacy_api->get_policy();