diff --git a/src/Makefile b/src/Makefile
index 7e006c512acd4f8f868067445f6f07de17996133..670a4daf102f28bba74c9254ab64ffbea072ba57 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/bitreader.c b/src/bitreader.c
index 0b406e01e9a4843a5999fee17f1decaecda6cb4e..d3553f0155d6d8db250f4839a4894e5a3b4670c9 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 0eefcee8f6b509b9f8d19ab5c07a64f2d95dc851..e6f984cd1e04211ca6ec389620a52296c5bb0c99 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_stream.overrun)
+      res = NULL; // overrun is always failure.
     // update the cache
     g_hash_table_replace(state->cache, &key, res);
 #ifdef CONSISTENCY_CHECK
@@ -166,7 +168,7 @@ const parser_t* range(const uint8_t lower, const uint8_t upper) {
   return (const parser_t*)ret;
 }
 
-const parser_t* notin(const uint8_t *options, int count) {
+const parser_t* not_in(const uint8_t *options, int count) {
   parser_t *ret = g_new(parser_t, 1);
   charset cs = new_charset();
   for (int i = 0; i < 256; i++)
@@ -604,11 +606,11 @@ static void test_left_factor_action(void) {
 
 }
 
-static void test_notin(void) {
+static void test_not_in(void) {
   uint8_t options[3] = { 'a', 'b', 'c' };
   uint8_t test1[1] = { 'd' };
   uint8_t test2[1] = { 'a' };
-  const parser_t *notin_ = notin(options, 3);
+  const parser_t *not_in_ = not_in(options, 3);
   parse_result_t *ret1 = parse(notin_, test1, 1);
   parse_result_t *ret2 = parse(notin_, test2, 1);
   g_check_cmpint(ret1->ast->uint, ==, 'd');
@@ -738,7 +740,7 @@ void register_parser_tests(void) {
   g_test_add_func("/core/parser/whitespace", test_whitespace);
   g_test_add_func("/core/parser/action", test_action);
   g_test_add_func("/core/parser/left_factor_action", test_left_factor_action);
-  g_test_add_func("/core/parser/notin", test_notin);
+  g_test_add_func("/core/parser/not_in", test_not_in);
   g_test_add_func("/core/parser/end_p", test_end_p);
   g_test_add_func("/core/parser/nothing_p", test_nothing_p);
   g_test_add_func("/core/parser/sequence", test_sequence);
diff --git a/src/hammer.h b/src/hammer.h
index 19eced8c187443b57990e9aa3a8358f902bcefa6..1b84861e432640f86d1d6bf8c277e20838840a1e 100644
--- a/src/hammer.h
+++ b/src/hammer.h
@@ -42,6 +42,7 @@ typedef struct input_stream {
   size_t length;
   char bit_offset;
   char endianness;
+  char overrun;
 } input_stream_t;
   
 typedef struct parse_state {
@@ -138,7 +139,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 *options, int count);
+const parser_t* not_in(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();