diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2020-04-03 11:09:21 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2020-04-08 16:26:06 -0700 |
commit | c81aefc5377888c7ac4f29f570249fd6c2fdb352 (patch) | |
tree | 22637ef997d456dd3e0af585bf7010f02c68b9c5 /src/util | |
parent | fffd8dca2de39ad4a683f0dce57cdca55ed2f600 (diff) |
Add additional effiency checks to sanity checker
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/asmap.cpp | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp index 5c3652f89b..5f3f53c393 100644 --- a/src/util/asmap.cpp +++ b/src/util/asmap.cpp @@ -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 } |