[PR] avcodec/cngdec: Fix SIGILL issue in cng_decode_frame() (PR #24012)
yongdev via ffmpeg-devel <[email protected]> Tue, 04 Aug 2026 21:10:30 -0000
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <178587783147.59.251898957659311718@29965ddac10e> |
PR #24012 opened by yongdev URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24012 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24012.patch The issue is caused by floating-point to integer overflow conversion at function av_clip_int16(p->filter_out[i + p->order]). The float value is out of bounds, which leads to undefined behavior and a SIGILL crash when compiled with -fsanitize=float-cast-overflow. - Handle NAN using isfinite() - Clip float value into valid range of int16 with av_clipf - Register the fate-comfortnoise test in FATE_VOICE. - Use the 'astats' filter to verify the output RMS level (expecting < -3dB). This allows detecting the regression on standard builds (where the bug causes positive peaks to invert to the negative rail, leading to RMS near 0dB) while avoiding flakiness from cross-platform float divergence on intermediate samples. >From ff9b8f3562d410603dd118b0fb6000745e8d9fe0 Mon Sep 17 00:00:00 2001 From: Yong Yu <[email protected]> Date: Sun, 14 Jun 2026 03:57:01 +0000 Subject: [PATCH 1/2] avcodec/cngdec: Fix SIGILL issue in cng_decode_frame() The issue is caused by floating-point to integer overflow conversion at function av_clip_int16(p->filter_out[i + p->order]). The float value is out of bounds, which leads to undefined behavior and a SIGILL crash when compiled with -fsanitize=float-cast-overflow. - Handle NAN using isfinite() - Clip float value into valid range of int16 with av_clipf - Register the fate-comfortnoise test in FATE_VOICE. - Use the 'astats' filter to verify the output RMS level (expecting < -3dB). This allows detecting the regression on standard builds (where the bug causes positive peaks to invert to the negative rail, leading to RMS near 0dB) while avoiding flakiness from cross-platform float divergence on intermediate samples. --- libavcodec/cngdec.c | 6 ++++-- tests/fate/voice.mak | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c index eb37c33eb4..9e7905ee6d 100644 --- a/libavcodec/cngdec.c +++ b/libavcodec/cngdec.c @@ -153,8 +153,10 @@ static int cng_decode_frame(AVCodecContext *avctx, AVFrame *frame, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; buf_out = (int16_t *)frame->data[0]; - for (i = 0; i < avctx->frame_size; i++) - buf_out[i] = av_clip_int16(p->filter_out[i + p->order]); + for (i = 0; i < avctx->frame_size; i++) { + const float f = p->filter_out[i + p->order]; + buf_out[i] = !isfinite(f) ? 0 : av_clipf(f, INT16_MIN, INT16_MAX); + } memcpy(p->filter_out, p->filter_out + avctx->frame_size, p->order * sizeof(*p->filter_out)); diff --git a/tests/fate/voice.mak b/tests/fate/voice.mak index 70855788d2..b6a5d7d113 100644 --- a/tests/fate/voice.mak +++ b/tests/fate/voice.mak @@ -94,5 +94,20 @@ fate-truespeech: CMD = pcm -i $(TARGET_SAMPLES)/truespeech/a6.wav fate-truespeech: CMP = oneoff fate-truespeech: REF = $(SAMPLES)/truespeech/a6.pcm +# This test reproduces a float-cast-overflow in the comfortnoise decoder +# (cngdec.c) when fed with a 24-byte all-zero G.723.1 frame. +# The bug causes positive float values to overflow to negative integer values +# during clipping, resulting in massive negative bias (RMS near 0dB). +# The fixed version clips correctly, resulting in quieter output (RMS < -3dB). +tests/data/g723_1-comfortnoise-sigill.bin: + $(M)mkdir -p tests/data + $(M)head -c 24 /dev/zero > $@ + +FATE_VOICE-$(call FILTERDEMDECENCMUX, ASTATS, G723_1, COMFORTNOISE, PCM_S16LE, NULL) += fate-comfortnoise +fate-comfortnoise: tests/data/g723_1-comfortnoise-sigill.bin +fate-comfortnoise: CMP = grep +fate-comfortnoise: REF = RMS level dB: \(-[3-9]\|-[1-9][0-9]\) +fate-comfortnoise: CMD = ffmpeg -f g723_1 -codec:a comfortnoise -i $(TARGET_PATH)/tests/data/g723_1-comfortnoise-sigill.bin -af astats -c:a pcm_s16le -f null - + FATE_SAMPLES_FFMPEG += $(FATE_VOICE-yes) fate-voice: $(FATE_VOICE-yes) -- 2.52.0 >From 531799372ff65b2a751516853523da7cf3f975bc Mon Sep 17 00:00:00 2001 From: yuyong05 <[email protected]> Date: Sun, 14 Jun 2026 03:57:01 +0000 Subject: [PATCH 2/2] avcodec/cngdec: Fix SIGILL issue in cng_decode_frame() The issue is caused by floating-point to integer overflow conversion at function av_clip_int16(p->filter_out[i + p->order]). The float value is out of bounds, which leads to undefined behavior and a SIGILL crash when compiled with -fsanitize=float-cast-overflow. - Handle NAN using isfinite() - Clip float value into valid range of int16 with av_clipf - Register the fate-comfortnoise test in FATE_VOICE. - Use the 'astats' filter to verify the output RMS level (expecting < -3dB). This allows detecting the regression on standard builds (where the bug causes positive peaks to invert to the negative rail, leading to RMS near 0dB) while avoiding flakiness from cross-platform float divergence on intermediate samples. --- tests/fate/voice.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/voice.mak b/tests/fate/voice.mak index b6a5d7d113..58805246ae 100644 --- a/tests/fate/voice.mak +++ b/tests/fate/voice.mak @@ -101,7 +101,7 @@ fate-truespeech: REF = $(SAMPLES)/truespeech/a6.pcm # The fixed version clips correctly, resulting in quieter output (RMS < -3dB). tests/data/g723_1-comfortnoise-sigill.bin: $(M)mkdir -p tests/data - $(M)head -c 24 /dev/zero > $@ + $(M)printf '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' > $@ FATE_VOICE-$(call FILTERDEMDECENCMUX, ASTATS, G723_1, COMFORTNOISE, PCM_S16LE, NULL) += fate-comfortnoise fate-comfortnoise: tests/data/g723_1-comfortnoise-sigill.bin -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]