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;