Commit bc1e992dab for freeswitch.com
commit bc1e992dab40dbbb43489b2b313d7e228a3a0a68
Author: Dmitry Verenitsin <morbit85@gmail.com>
Date: Sun Aug 9 02:05:39 2026 +0500
[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.
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;