aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2020-04-03 11:09:21 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2020-04-08 16:26:06 -0700
commitc81aefc5377888c7ac4f29f570249fd6c2fdb352 (patch)
tree22637ef997d456dd3e0af585bf7010f02c68b9c5 /src/util
parentfffd8dca2de39ad4a683f0dce57cdca55ed2f600 (diff)
Add additional effiency checks to sanity checker
Diffstat (limited to 'src/util')
-rw-r--r--src/util/asmap.cpp11
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
}