From dc0a7572f7d076028fdaf9e546b1d09ea8ee58ed Mon Sep 17 00:00:00 2001 From: Dan Hirsch Date: Thu, 10 May 2012 14:32:11 +0100 Subject: [PATCH 1/2] Added overrun protection --- src/bitreader.c | 28 ++++++++++++++++++++++++++-- src/hammer.c | 2 ++ src/hammer.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/bitreader.c b/src/bitreader.c index 0b406e0..d3553f0 100644 --- a/src/bitreader.c +++ b/src/bitreader.c @@ -13,14 +13,37 @@ long long read_bits(input_stream_t* state, int count, char signed_p) { // BUG: Does not long long out = 0; int offset = 0; + int final_shift = 0; long long msb = (!!signed_p) << (count - 1); // 0 if unsigned, else 1 << (nbits - 1) - // BUG: does not stop early in case of + + + // overflow check... + int bits_left = (state->length - state->index); // well, bytes for now + if (bits_left <= 64) { // Large enough to handle any valid count, but small enough that overflow isn't a problem. + // not in danger of overflowing, so add in bits + // add in number of bits... + if (state->endianness & BIT_BIG_ENDIAN) + bits_left = (bits_left << 3) - 8 + state->bit_offset; + else + bits_left = (bits_left << 3) - state->bit_offset; + if (bits_left < count) { + if (state->endianness & BYTE_BIG_ENDIAN) + final_shift = count - bits_left; + else + final_shift = 0; + count = bits_left; + state->overrun = true; + } else + final_shift = 0; + } if ((state->bit_offset & 0x7) == 0 && (count & 0x7) == 0) { // fast path if (state->endianness & BYTE_BIG_ENDIAN) { - while (count > 0) + while (count > 0) { + count -= 8; out = (out << 8) | state->input[state->index++]; + } } else { while (count > 0) { count -= 8; @@ -65,6 +88,7 @@ long long read_bits(input_stream_t* state, int count, char signed_p) { count -= segment_len; } } + out <<= final_shift; return (out ^ msb) - msb; // perform sign extension } diff --git a/src/hammer.c b/src/hammer.c index 7d1dabb..0450f7d 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -72,6 +72,8 @@ parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) { // It doesn't exist... run the parse_result_t *res; res = parser->fn(parser->env, state); + if (state->input.overrun) + res = NULL; // overrun is always failure. // update the cache g_hash_table_replace(state->cache, &key, res); #ifdef CONSISTENCY_CHECK diff --git a/src/hammer.h b/src/hammer.h index b0a9c1a..e1afab6 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -41,6 +41,7 @@ typedef struct input_stream { size_t length; char bit_offset; char endianness; + char overrun; } input_stream_t; typedef struct parse_state { From 99804b2abfb807d26d14f2f782f3f33651f9f950 Mon Sep 17 00:00:00 2001 From: Dan Hirsch Date: Fri, 11 May 2012 23:35:21 +0100 Subject: [PATCH 2/2] Added pretty printer --- src/Makefile | 4 ++-- src/hammer.c | 2 +- src/hammer.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 7e006c5..670a4da 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,7 +14,7 @@ all: libhammer.a test_suite test_suite: test_suite.o libhammer.a $(call hush, "Linking $@") $(CC) -o $@ $^ $(LDFLAGS) -libhammer.a: bitreader.o hammer.o +libhammer.a: bitreader.o hammer.o pprint.o bitreader.o: test_suite.h -hammer.o: hammer.h \ No newline at end of file +hammer.o: hammer.h diff --git a/src/hammer.c b/src/hammer.c index 0450f7d..66bc246 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -72,7 +72,7 @@ parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) { // It doesn't exist... run the parse_result_t *res; res = parser->fn(parser->env, state); - if (state->input.overrun) + if (state->input_stream.overrun) res = NULL; // overrun is always failure. // update the cache g_hash_table_replace(state->cache, &key, res); diff --git a/src/hammer.h b/src/hammer.h index e1afab6..d58dc31 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -103,7 +103,7 @@ const parser_t* whitespace(const parser_t* p); const parser_t* left_factor_action(const parser_t* p); /* Parse a single character *NOT* in charset */ -const parser_t* notin(const uint8_t charset, int length); +const parser_t* notin(const uint8_t *charset, int length); /* A no-argument parser that succeeds if there is no more input to parse. */ const parser_t* end_p();