Fail or return 0 if input runs dry
authorMathis Rosenhauer <rosenhauer@dkrz.de>
Tue, 27 Jun 2017 14:23:50 +0000 (16:23 +0200)
committerMathis Rosenhauer <rosenhauer@dkrz.de>
Fri, 30 Jun 2017 15:06:54 +0000 (17:06 +0200)
Found by libFuzzer

src/decode.c
src/decode.h

index edb5af1..a37acdd 100644 (file)
@@ -229,7 +229,6 @@ static inline uint32_t direct_get(struct aec_stream *strm, int n)
 
     struct internal_state *state = strm->state;
     int b;
-
     if (state->bitp < n)
     {
         b = (63 - state->bitp) >> 3;
@@ -308,6 +307,9 @@ static inline uint32_t direct_get_fs(struct aec_stream *strm)
         state->acc = 0;
 
     while (state->acc == 0) {
+        if (strm->avail_in < 7)
+            return 0;
+
         state->acc = (state->acc << 56)
             | ((uint64_t)strm->next_in[0] << 48)
             | ((uint64_t)strm->next_in[1] << 40)
@@ -475,6 +477,9 @@ static int m_split(struct aec_stream *strm)
             state->rsip[i] = direct_get_fs(strm) << k;
 
         if (k) {
+            if (strm->avail_in < (k * strm->block_size) / 8 + 9)
+                return M_ERROR;
+
             for (i = state->ref; i < strm->block_size; i++)
                 *state->rsip++ += direct_get(strm, k);
         } else {
@@ -566,6 +571,8 @@ static int m_se_decode(struct aec_stream *strm)
         if (fs_ask(strm) == 0)
             return M_EXIT;
         m = state->fs;
+        if (m > SE_TABLE_SIZE)
+            return M_ERROR;
         d1 = m - state->se_table[2 * m + 1];
 
         if ((state->i & 1) == 0) {
@@ -589,7 +596,8 @@ static int m_se_decode(struct aec_stream *strm)
 static int m_se(struct aec_stream *strm)
 {
     uint32_t i;
-    int32_t m, d1;
+    uint32_t m;
+    int32_t d1;
     struct internal_state *state = strm->state;
 
     if (BUFFERSPACE(strm)) {
@@ -597,6 +605,10 @@ static int m_se(struct aec_stream *strm)
 
         while (i < strm->block_size) {
             m = direct_get_fs(strm);
+
+            if (m > SE_TABLE_SIZE)
+                return M_ERROR;
+
             d1 = m - state->se_table[2 * m + 1];
 
             if ((i & 1) == 0) {
@@ -763,7 +775,7 @@ int aec_decode_init(struct aec_stream *strm)
     }
 
     state->in_blklen = (strm->block_size * strm->bits_per_sample
-                        + state->id_len) / 8 + 9;
+                        + state->id_len) / 8 + 16;
 
     modi = 1UL << state->id_len;
     state->id_table = malloc(modi * sizeof(int (*)(struct aec_stream *)));
index 8a45547..b62ba85 100644 (file)
@@ -63,6 +63,8 @@
 
 #define MIN(a, b) (((a) < (b))? (a): (b))
 
+#define SE_TABLE_SIZE 90
+
 struct aec_stream;
 
 struct internal_state {
@@ -89,7 +91,7 @@ struct internal_state {
     uint32_t xmax;
 
      /* length of uncompressed input block should be the longest
-        possible block */
+        legal block */
     uint32_t in_blklen;
 
     /* length of output block in bytes */
@@ -129,7 +131,7 @@ struct internal_state {
     uint32_t *flush_start;
 
     /* table for decoding second extension option */
-    int se_table[182];
+    int se_table[2 * (SE_TABLE_SIZE + 1)];
 } decode_state;
 
 #endif /* DECODE_H */