From: Sebastian Dröge <sebast...@centricular.com>

Instead of failing to parse such CDP packets, simply skip over the time
code data and read the CC data following it.

Also add some more length checks in related to this and the existing
parsing code to prevent reading out of bounds memory.
---
 libavdevice/decklink_dec.cpp | 60 ++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 13 deletions(-)

diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 2e41b587e8..2194e84226 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -329,18 +329,30 @@ static uint8_t* 
teletext_data_unit_from_ancillary_packet(uint16_t *py, uint16_t
 static uint8_t *vanc_to_cc(AVFormatContext *avctx, uint16_t *buf, size_t words,
                            unsigned &cc_count)
 {
-    size_t i, len = (buf[5] & 0xff) + 6 + 1;
+    size_t i, len;
     uint8_t cdp_sum, rate;
     uint16_t hdr, ftr;
+    uint8_t flags;
     uint8_t *cc;
-    uint16_t *cdp = &buf[6]; // CDP follows
+    uint16_t *cdp;
+
+    /* validity of this length is already checked by the caller */
+    len = (buf[5] & 0xff) + 6 + 1;
+
+    cdp = &buf[6]; // CDP follows
+    len -= 7; // remove VANC header and checksum
+
+    /* 7 bytes CDP header, 4 bytes CDP footer */
+    if (len < 7 + 4) {
+        av_log(avctx, AV_LOG_WARNING, "Invalid CDP packet length %zu < %d\n", 
len, 7 + 4);
+        return NULL;
+    }
+
     if (cdp[0] != 0x96 || cdp[1] != 0x69) {
         av_log(avctx, AV_LOG_WARNING, "Invalid CDP header 0x%.2x 0x%.2x\n", 
cdp[0], cdp[1]);
         return NULL;
     }
 
-    len -= 7; // remove VANC header and checksum
-
     if (cdp[2] != len) {
         av_log(avctx, AV_LOG_WARNING, "CDP len %d != %zu\n", cdp[2], len);
         return NULL;
@@ -366,26 +378,48 @@ static uint8_t *vanc_to_cc(AVFormatContext *avctx, 
uint16_t *buf, size_t words,
         return NULL;
     }
 
-    if (!(cdp[4] & 0x43)) /* ccdata_present | caption_service_active | 
reserved */ {
-        av_log(avctx, AV_LOG_WARNING, "CDP flags invalid (0x%.2x)\n", cdp[4]);
+    flags = cdp[4];
+    if (!(flags & 0x43)) /* ccdata_present | caption_service_active | reserved 
*/ {
+        av_log(avctx, AV_LOG_WARNING, "CDP flags invalid (0x%.2x)\n", flags);
         return NULL;
     }
 
     hdr = (cdp[5] << 8) | cdp[6];
-    if (cdp[7] != 0x72) /* ccdata_id */ {
+
+    /* skip over the CDP header parsed above */
+    cdp += 7;
+    len -= 7;
+
+    if ((flags & 0x80)) /* time_code_present */ {
+      /* time code is stored in 5 bytes, skip over them */
+      if (len < 5) {
+        av_log(avctx, AV_LOG_WARNING, "CDP length too small for time code 
section\n");
+        return NULL;
+      }
+      cdp += 5;
+      len -= 5;
+    }
+
+    if (len < 2) {
+      av_log(avctx, AV_LOG_WARNING, "CDP length too small for CC data 
section\n");
+      return NULL;
+    }
+
+    if (cdp[0] != 0x72) /* ccdata_id */ {
         av_log(avctx, AV_LOG_WARNING, "Invalid ccdata_id 0x%.2x\n", cdp[7]);
         return NULL;
     }
 
-    cc_count = cdp[8];
+    cc_count = cdp[1];
     if (!(cc_count & 0xe0)) {
         av_log(avctx, AV_LOG_WARNING, "Invalid cc_count 0x%.2x\n", cc_count);
         return NULL;
     }
 
     cc_count &= 0x1f;
-    if ((len - 13) < cc_count * 3) {
-        av_log(avctx, AV_LOG_WARNING, "Invalid cc_count %d (> %zu)\n", 
cc_count * 3, len - 13);
+    /* 6 = 2 bytes for the CC data header read above and 4 bytes for the CDP 
footer */
+    if (len < cc_count * 3 + 6) {
+        av_log(avctx, AV_LOG_WARNING, "Invalid cc_count %d (> %zu)\n", 
cc_count * 3, len - 6);
         return NULL;
     }
 
@@ -407,9 +441,9 @@ static uint8_t *vanc_to_cc(AVFormatContext *avctx, uint16_t 
*buf, size_t words,
     }
 
     for (size_t i = 0; i < cc_count; i++) {
-        cc[3*i + 0] = cdp[9 + 3*i+0] /* & 3 */;
-        cc[3*i + 1] = cdp[9 + 3*i+1];
-        cc[3*i + 2] = cdp[9 + 3*i+2];
+        cc[3*i + 0] = cdp[2 + 3*i+0] /* & 3 */;
+        cc[3*i + 1] = cdp[2 + 3*i+1];
+        cc[3*i + 2] = cdp[2 + 3*i+2];
     }
 
     cc_count *= 3;
-- 
2.29.2

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to