Skip to content

Commit

Permalink
Add more efficiency sanity checks
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa committed Apr 3, 2020
1 parent 5a8e7c5 commit 00fe329
Showing 1 changed file with 10 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/util/asmap.cpp
Expand Up @@ -123,11 +123,14 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
const std::vector<bool>::const_iterator begin = asmap.begin(), endpos = asmap.end();
std::vector<bool>::const_iterator pos = begin;
std::vector<std::pair<uint32_t, int>> jumps; // All future positions we may jump to (offset, bits left); ordered from far to near
Instruction prevopcode = Instruction::JUMP;
bool lastmatch_full = false;
while (pos != endpos) {
uint32_t offset = pos - begin;
if (jumps.size() && offset >= jumps.back().first) return false; // We executed past a jump target
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.size() == 0) {
Expand All @@ -144,6 +147,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);
Expand All @@ -154,15 +158,21 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
uint32_t new_offset = pos - begin + jump;
if (jumps.size() && new_offset >= jumps.back().first) return false; // Overlapping jumps
jumps.emplace_back(new_offset, bits);
prevopcode = Instruction::JUMP;
} else if (opcode == Instruction::MATCH) {
if (prevopcode == Instruction::MATCH && !lastmatch_full) return false; // There should not be any MATCH after a non-full MATCH (they could be reshuffled/turned into one)
uint32_t match = DecodeMatch(pos, endpos);
if (match == INVALID) return false; // Match bits straddle EOF
int matchlen = CountBits(match) - 1;
if (bits < matchlen) return false; // Consuming bits past the end of the input
bits -= matchlen;
prevopcode = Instruction::MATCH;
lastmatch_full = (matchlen == 8);
} 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
}
Expand Down

0 comments on commit 00fe329

Please sign in to comment.