diff mbox series

[FFmpeg-devel,v1] libavcodec/flac_parser: Validate subframe zero bit and type

Message ID 20211013161526.83708-1-mattias.wadman@gmail.com
State New
Headers show
Series [FFmpeg-devel,v1] libavcodec/flac_parser: Validate subframe zero bit and type
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Mattias Wadman Oct. 13, 2021, 4:15 p.m. UTC
Reduces the risk of finding false frames that happens to have valid values and CRC.

Fixes ticket #9185 ffmpeg flac decoder incorrectly finds junk frame
https://trac.ffmpeg.org/ticket/9185
---
 libavcodec/flac_parser.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
index d3d9c889a1..2c550507fc 100644
--- a/libavcodec/flac_parser.c
+++ b/libavcodec/flac_parser.c
@@ -96,8 +96,34 @@  static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
                                  FLACFrameInfo *fi)
 {
     GetBitContext gb;
-    init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8);
-    return !ff_flac_decode_frame_header(avctx, &gb, fi, 127);
+    uint8_t subframe_type;
+
+    // header plus one byte from first subframe
+    init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8 + 8);
+    if (ff_flac_decode_frame_header(avctx, &gb, fi, 127)) {
+        return 0;
+    }
+    // subframe zero bit
+    if (get_bits1(&gb) != 0) {
+        return 0;
+    }
+    // subframe type
+    // 000000 : SUBFRAME_CONSTANT
+    // 000001 : SUBFRAME_VERBATIM
+    // 00001x : reserved
+    // 0001xx : reserved
+    // 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved
+    // 01xxxx : reserved
+    // 1xxxxx : SUBFRAME_LPC, xxxxx=order-1
+    subframe_type = get_bits(&gb, 6);
+    if (!(subframe_type == 0 ||
+          subframe_type == 1 ||
+          ((subframe_type >= 8) && (subframe_type <= 12)) ||
+          (subframe_type >= 32))) {
+        return 0;
+    }
+
+    return 1;
 }
 
 /**