rtptheoradepay: fix in-band configuration parsing
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 7 May 2010 13:31:03 +0000 (15:31 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 10 May 2010 11:35:50 +0000 (13:35 +0200)
Also make configuration header parsing a bit more relaxed with respect
to length field interpretation.

gst/rtp/gstrtptheoradepay.c

index e864870..860a113 100644 (file)
@@ -191,6 +191,7 @@ gst_rtp_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
     guint8 n_headers, b;
     GstRtpTheoraConfig *conf;
     guint *h_sizes;
+    guint extra = 1;
 
     if (size < 6)
       goto too_small;
@@ -206,7 +207,8 @@ gst_rtp_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
 
     /* FIXME check if we already got this ident */
 
-    if (size < length)
+    /* length might also include count of following size fields */
+    if (size < length && size + 1 != length)
       goto too_small;
 
     /* read header sizes we read 2 sizes, the third size (for which we allocate
@@ -221,6 +223,7 @@ gst_rtp_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
           goto too_small;
         b = *data++;
         size--;
+        extra++;
         h_size = (h_size << 7) | (b & 0x7f);
       } while (b & 0x80);
       GST_DEBUG_OBJECT (rtptheoradepay, "headers %d: size: %u", j, h_size);
@@ -239,8 +242,15 @@ gst_rtp_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
       guint h_size;
 
       h_size = h_sizes[j];
-      if (size < h_size)
-        goto too_small;
+      if (size < h_size) {
+        if (j != n_headers || size + extra != h_size) {
+          goto too_small;
+        } else {
+          /* otherwise means that overall length field contained total length,
+           * including extra fields */
+          h_size -= extra;
+        }
+      }
 
       GST_DEBUG_OBJECT (rtptheoradepay, "reading header %d, size %u", j,
           h_size);
@@ -265,7 +275,8 @@ too_small:
 
 static gboolean
 gst_rtp_theora_depay_parse_inband_configuration (GstRtpTheoraDepay *
-    rtptheoradepay, guint ident, guint8 * configuration, guint size)
+    rtptheoradepay, guint ident, guint8 * configuration, guint size,
+    guint length)
 {
   GstBuffer *confbuf;
   guint8 *conf;
@@ -274,14 +285,16 @@ gst_rtp_theora_depay_parse_inband_configuration (GstRtpTheoraDepay *
     return FALSE;
 
   /* transform inline to out-of-band and parse that one */
-  confbuf = gst_buffer_new_and_alloc (size + 3);
+  confbuf = gst_buffer_new_and_alloc (size + 9);
   conf = GST_BUFFER_DATA (confbuf);
   /* 1 header */
   GST_WRITE_UINT32_BE (conf, 1);
   /* write Ident */
   GST_WRITE_UINT24_BE (conf + 4, ident);
+  /* write sort-of-length */
+  GST_WRITE_UINT16_BE (conf + 7, length);
   /* copy remainder */
-  memcpy (conf + 7, configuration + 4, size - 4);
+  memcpy (conf + 9, configuration, size);
 
   return gst_rtp_theora_depay_parse_configuration (rtptheoradepay, confbuf);
 }
@@ -550,7 +563,7 @@ gst_rtp_theora_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
     if (G_UNLIKELY (TDT == 1)) {
       GST_DEBUG_OBJECT (rtptheoradepay, "in-band configuration");
       if (!gst_rtp_theora_depay_parse_inband_configuration (rtptheoradepay,
-              ident, payload, payload_len))
+              ident, payload, payload_len, length))
         goto invalid_configuration;
       goto no_output;
     }