summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathis Rosenhauer <rosenhauer@dkrz.de>2017-06-27 14:23:50 (GMT)
committerMathis Rosenhauer <rosenhauer@dkrz.de>2017-06-30 15:06:54 (GMT)
commit62f82d001059962bc0fca7272536b394ab823d42 (patch)
tree7980037d0bc555e0d99abf4ea5234bf1e1f4cfda
parent8cd1a00dcbc58d69b5bff2ed93a2f42d491e54cf (diff)
downloadlibaec-62f82d001059962bc0fca7272536b394ab823d42.zip
libaec-62f82d001059962bc0fca7272536b394ab823d42.tar.gz
libaec-62f82d001059962bc0fca7272536b394ab823d42.tar.bz2
Fail or return 0 if input runs dry
Found by libFuzzer
-rw-r--r--src/decode.c18
-rw-r--r--src/decode.h6
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 */