Skip to content

Commit bc1e992

Browse files
authored
[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.
1 parent 2c8802e commit bc1e992

1 file changed

Lines changed: 16 additions & 5 deletions

File tree

src/mod/codecs/mod_silk/mod_silk.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,13 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
328328
uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
329329
{
330330
struct silk_context *context = codec->private_info;
331-
SKP_int16 ret, len;
332331
int16_t *target = decoded_data;
333332
switch_core_session_t *session = codec->session;
334333
switch_jb_t *jb = NULL;
335334
SKP_int lost_flag = (*flag & SFF_PLC);
336335
switch_bool_t did_lbrr = SWITCH_FALSE;
337336
int i;
337+
int decoded_frames = 0;
338338

339339
*decoded_data_len = 0;
340340

@@ -368,6 +368,8 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
368368
}
369369

370370
do {
371+
SKP_int16 ret, len = 0;
372+
371373
ret = (SKP_int16)SKP_Silk_SDK_Decode(context->dec_state,
372374
&context->decoder_object,
373375
lost_flag,
@@ -379,12 +381,21 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
379381
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret);
380382
printSilkError(ret);
381383
/* if FEC was activated, we can ignore bit errors*/
382-
if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr))
383-
return SWITCH_STATUS_FALSE;
384+
if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr)) {
385+
return SWITCH_STATUS_FALSE;
386+
}
384387
}
385388

386-
target += len;
387-
*decoded_data_len += (len * 2);
389+
if (len > 0) {
390+
target += len;
391+
*decoded_data_len += (len * 2);
392+
}
393+
394+
/* A conformant SILK packet decodes to at most MAX_INPUT_FRAMES internal frames; stop there so
395+
the accumulated PCM cannot run past the destination buffer regardless of the bitstream. */
396+
if (++decoded_frames >= MAX_INPUT_FRAMES) {
397+
break;
398+
}
388399
} while (context->decoder_object.moreInternalDecoderFrames);
389400

390401
return SWITCH_STATUS_SUCCESS;

0 commit comments

Comments
 (0)