message: Add additional effiency checks to sanity checker
diff: @@ -126,11 +126,14 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
  std::vector<bool>::const_iterator pos = begin;
  std::vector<std::pair<uint32_t, int>> jumps; // All future positions we may jump to (bit offset in asmap -> bits to consume left)
  jumps.reserve(bits);
  + Instruction prevopcode = Instruction::JUMP;
  + bool had_incomplete_match = false;
  while (pos != endpos) {
  uint32_t offset = pos - begin;
  if (!jumps.empty() && offset >= jumps.back().first) return false; // There was a jump into the middle of the previous instruction
  Instruction opcode = DecodeType(pos, endpos);
  if (opcode == Instruction::RETURN) {
  + if (prevopcode == Instruction::DEFAULT) return false; // There should not be any RETURN immediately after a DEFAULT (could be combined into just RETURN)
  uint32_t asn = DecodeASN(pos, endpos);
  if (asn == INVALID) return false; // ASN straddles EOF
  if (jumps.empty()) {
  @@ -147,6 +150,7 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
  if (offset != jumps.back().first) return false; // Unreachable code
  bits = jumps.back().second; // Restore the number of bits we would have had left after this jump
  jumps.pop_back();
  + prevopcode = Instruction::JUMP;
  }
  } else if (opcode == Instruction::JUMP) {
  uint32_t jump = DecodeJump(pos, endpos);
  @@ -157,15 +161,22 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
  uint32_t jump_offset = pos - begin + jump;
  if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
  jumps.emplace_back(jump_offset, bits);
  + prevopcode = Instruction::JUMP;
  } else if (opcode == Instruction::MATCH) {
  uint32_t match = DecodeMatch(pos, endpos);
  if (match == INVALID) return false; // Match bits straddle EOF
  int matchlen = CountBits(match) - 1;
  + if (prevopcode != Instruction::MATCH) had_incomplete_match = false;
  + if (matchlen < 8 && had_incomplete_match) return false; // Within a sequence of matches only at most one should be incomplete
  + had_incomplete_match = (matchlen < 8);
  if (bits < matchlen) return false; // Consuming bits past the end of the input
  bits -= matchlen;
  + prevopcode = Instruction::MATCH;
  } else if (opcode == Instruction::DEFAULT) {
  + if (prevopcode == Instruction::DEFAULT) return false; // There should not be two successive DEFAULTs (they could be combined into one)
  uint32_t asn = DecodeASN(pos, endpos);
  if (asn == INVALID) return false; // ASN straddles EOF
  + prevopcode = Instruction::DEFAULT;
  } else {
  return false; // Instruction straddles EOF
  }
  