[xiph-commits] r11067 - trunk/theora/lib

giles at svn.xiph.org giles at svn.xiph.org
Tue Mar 28 17:35:20 PST 2006


Author: giles
Date: 2006-03-28 17:35:18 -0800 (Tue, 28 Mar 2006)
New Revision: 11067

Modified:
   trunk/theora/lib/decode.c
Log:
Add more input bounds checking; the previous code segfaulted when handed 
very short packets. Hack some use of the (apparently unused) 
DecoderErrorCode state variable to propagate errors from some void 
funtions. Some of these should just return OC_BADPACKET directly.

Note that we still do our best to continue, so playback is possible
(but not correct) if OC_BADPACKET is ignored. The main difference here
is that a packet is truncated before the end of the header we just
fail to construct a new frame instead of, well, segfaulting.


Modified: trunk/theora/lib/decode.c
===================================================================
--- trunk/theora/lib/decode.c	2006-03-28 23:33:42 UTC (rev 11066)
+++ trunk/theora/lib/decode.c	2006-03-29 01:35:18 UTC (rev 11067)
@@ -72,17 +72,29 @@
   /* Quality (Q) index */
   NQIndex = 0;
   theora_read(pbi->opb,6,&ret);
+  if (ret < 0 || ret >= 64) {	/* range check */
+    ret = 0;
+    pbi->DecoderErrorCode = 1;
+  }
   DctQIndex[NQIndex++] = (unsigned char)ret;
 
   theora_read(pbi->opb,1,&ret);
   SpareBits = (unsigned char)ret;
   if (SpareBits) {
     theora_read(pbi->opb,6,&ret);
+    if (ret < 0 || ret >= 64) {	/* range check */
+      ret = 0;
+      pbi->DecoderErrorCode = 1;
+    }
     DctQIndex[NQIndex++] = (unsigned char)ret;
     theora_read(pbi->opb,1,&ret);
     SpareBits = (unsigned char)ret;
     if (SpareBits) {
       theora_read(pbi->opb,6,&ret);
+      if (ret < 0 || ret >= 64) {	/* range check */
+        ret = 0;
+        pbi->DecoderErrorCode = 1;
+      }
       DctQIndex[NQIndex++] = (unsigned char)ret;
     }
   }
@@ -103,7 +115,7 @@
   /* Set this frame quality value and tables from the coded Q Index */
   UpdateQ(pbi, DctQIndex[0]);
 
-  return 1;
+  return pbi->DecoderErrorCode;
 }
 
 void SetFrameType( PB_INSTANCE *pbi,unsigned char FrType ){
@@ -123,13 +135,13 @@
 static int LoadFrame(PB_INSTANCE *pbi){
 
   /* Load the frame header (including the frame size). */
-  if ( LoadFrameHeader(pbi) ){
+  if ( LoadFrameHeader(pbi) == 0 ){
     /* Read in the updated block map */
     QuadDecodeDisplayFragments( pbi );
-    return 1;
+    return 0;
   }
 
-  return 0;
+  return pbi->DecoderErrorCode;
 }
 
 static void DecodeModes (PB_INSTANCE *pbi,
@@ -692,8 +704,16 @@
   /* Get the DC huffman table choice for Y and then UV */
   theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret); 
   DcHuffChoice1 = ret + DC_HUFF_OFFSET;
+  if (ret < 0 || DcHuffChoice1 >= NUM_HUFF_TABLES) {
+    DcHuffChoice1 = DC_HUFF_OFFSET;
+    pbi->DecoderErrorCode = 1;
+  }
   theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret); 
   DcHuffChoice2 = ret + DC_HUFF_OFFSET;
+  if (ret < 0 || DcHuffChoice2 >= NUM_HUFF_TABLES) {
+    DcHuffChoice2 = DC_HUFF_OFFSET;
+    pbi->DecoderErrorCode = 1;
+  }
 
   /* UnPack DC coefficients / tokens */
   CodedBlockListPtr = pbi->CodedBlockList;
@@ -730,8 +750,16 @@
 
   theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret); 
   AcHuffIndex1 = ret + AC_HUFF_OFFSET;
+  if (ret < 0 || AcHuffIndex1 >= NUM_HUFF_TABLES) {
+    AcHuffIndex1 = AC_HUFF_OFFSET;
+    pbi->DecoderErrorCode = 1;
+  }
   theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret); 
   AcHuffIndex2 = ret + AC_HUFF_OFFSET;
+  if (ret < 0 || AcHuffIndex2 >= NUM_HUFF_TABLES) {
+    AcHuffIndex2 = AC_HUFF_OFFSET;
+    pbi->DecoderErrorCode = 1;
+  }
 
   /* Unpack Lower AC coefficients. */
   while ( EncodedCoeffs < 64 ) {
@@ -813,12 +841,15 @@
 
   /* Decode the modes data */
   DecodeModes( pbi, pbi->YSBRows, pbi->YSBCols);
+  if (pbi->DecoderErrorCode) return;
 
   /* Unpack and decode the motion vectors. */
   DecodeMVectors ( pbi, pbi->YSBRows, pbi->YSBCols);
+  if (pbi->DecoderErrorCode) return;
 
   /* Unpack and decode the actual video data. */
   UnPackVideo(pbi);
+  if (pbi->DecoderErrorCode) return;
 
   /* Reconstruct and display the frame */
   ReconRefFrames(pbi);
@@ -827,22 +858,18 @@
 
 
 int LoadAndDecode(PB_INSTANCE *pbi){
-  int    LoadFrameOK;
 
   /* Reset the DC predictors. */
   pbi->InvLastIntraDC = 0;
   pbi->InvLastInterDC = 0;
 
-  /* Load the next frame. */
-  LoadFrameOK = LoadFrame(pbi);
-
-  if ( LoadFrameOK ){
+  if ( LoadFrame(pbi) == 0 ){
     pbi->LastFrameQualityValue = pbi->ThisFrameQualityValue;
 
     /* Decode the data into the fragment buffer. */
     DecodeData(pbi);
-    return(0);
+    if (pbi->DecoderErrorCode == 0) return 0;
   }
 
-  return(OC_BADPACKET);
+  return OC_BADPACKET;
 }



More information about the commits mailing list