From 62f82d001059962bc0fca7272536b394ab823d42 Mon Sep 17 00:00:00 2001 From: Mathis Rosenhauer Date: Tue, 27 Jun 2017 16:23:50 +0200 Subject: Fail or return 0 if input runs dry Found by libFuzzer --- src/decode.c | 18 +++++++++++++++--- src/decode.h | 6 ++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/decode.c b/src/decode.c index edb5af1..a37acdd 100644 --- a/src/decode.c +++ b/src/decode.c @@ -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 *))); diff --git a/src/decode.h b/src/decode.h index 8a45547..b62ba85 100644 --- a/src/decode.h +++ b/src/decode.h @@ -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 */ -- cgit v1.2.3