From bc1e992dab40dbbb43489b2b313d7e228a3a0a68 Mon Sep 17 00:00:00 2001 From: Dmitry Verenitsin Date: Sun, 9 Aug 2026 02:05:39 +0500 Subject: [PATCH] [mod_silk] Bound decode loop to the codec's frame limit (#3116) `switch_silk_decode()` ran its `do`/`while` decode loop while the SDK kept reporting more internal frames, advancing the output pointer each pass with no cap. The destination is a fixed-size PCM buffer, so a stream reporting more internal frames than a conformant packet can carry let the accumulated write run past its end. Stop after `MAX_INPUT_FRAMES` internal frames, the most a conformant SILK packet can hold, so the accumulated PCM stays within the destination regardless of the bitstream. Declare the per-pass sample count inside the loop so it resets to zero each iteration, and advance the output pointer and length only when it is positive. A pass that writes no samples, including a tolerated FEC payload error that leaves the count untouched, then contributes nothing instead of advancing on a stale count from an earlier pass or on a negative value. --- src/mod/codecs/mod_silk/mod_silk.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mod/codecs/mod_silk/mod_silk.c b/src/mod/codecs/mod_silk/mod_silk.c index 507309a362..9a84989e91 100644 --- a/src/mod/codecs/mod_silk/mod_silk.c +++ b/src/mod/codecs/mod_silk/mod_silk.c @@ -328,13 +328,13 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) { struct silk_context *context = codec->private_info; - SKP_int16 ret, len; int16_t *target = decoded_data; switch_core_session_t *session = codec->session; switch_jb_t *jb = NULL; SKP_int lost_flag = (*flag & SFF_PLC); switch_bool_t did_lbrr = SWITCH_FALSE; int i; + int decoded_frames = 0; *decoded_data_len = 0; @@ -368,6 +368,8 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec, } do { + SKP_int16 ret, len = 0; + ret = (SKP_int16)SKP_Silk_SDK_Decode(context->dec_state, &context->decoder_object, lost_flag, @@ -379,12 +381,21 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret); printSilkError(ret); /* if FEC was activated, we can ignore bit errors*/ - if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr)) - return SWITCH_STATUS_FALSE; + if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr)) { + return SWITCH_STATUS_FALSE; + } } - target += len; - *decoded_data_len += (len * 2); + if (len > 0) { + target += len; + *decoded_data_len += (len * 2); + } + + /* A conformant SILK packet decodes to at most MAX_INPUT_FRAMES internal frames; stop there so + the accumulated PCM cannot run past the destination buffer regardless of the bitstream. */ + if (++decoded_frames >= MAX_INPUT_FRAMES) { + break; + } } while (context->decoder_object.moreInternalDecoderFrames); return SWITCH_STATUS_SUCCESS;