Skip to content

Commit c81aefc

Browse files
committed
Add additional effiency checks to sanity checker
1 parent fffd8dc commit c81aefc

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

src/util/asmap.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,14 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
126126
std::vector<bool>::const_iterator pos = begin;
127127
std::vector<std::pair<uint32_t, int>> jumps; // All future positions we may jump to (bit offset in asmap -> bits to consume left)
128128
jumps.reserve(bits);
129+
Instruction prevopcode = Instruction::JUMP;
130+
bool had_incomplete_match = false;
129131
while (pos != endpos) {
130132
uint32_t offset = pos - begin;
131133
if (!jumps.empty() && offset >= jumps.back().first) return false; // There was a jump into the middle of the previous instruction
132134
Instruction opcode = DecodeType(pos, endpos);
133135
if (opcode == Instruction::RETURN) {
136+
if (prevopcode == Instruction::DEFAULT) return false; // There should not be any RETURN immediately after a DEFAULT (could be combined into just RETURN)
134137
uint32_t asn = DecodeASN(pos, endpos);
135138
if (asn == INVALID) return false; // ASN straddles EOF
136139
if (jumps.empty()) {
@@ -147,6 +150,7 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
147150
if (offset != jumps.back().first) return false; // Unreachable code
148151
bits = jumps.back().second; // Restore the number of bits we would have had left after this jump
149152
jumps.pop_back();
153+
prevopcode = Instruction::JUMP;
150154
}
151155
} else if (opcode == Instruction::JUMP) {
152156
uint32_t jump = DecodeJump(pos, endpos);
@@ -157,15 +161,22 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
157161
uint32_t jump_offset = pos - begin + jump;
158162
if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
159163
jumps.emplace_back(jump_offset, bits);
164+
prevopcode = Instruction::JUMP;
160165
} else if (opcode == Instruction::MATCH) {
161166
uint32_t match = DecodeMatch(pos, endpos);
162167
if (match == INVALID) return false; // Match bits straddle EOF
163168
int matchlen = CountBits(match) - 1;
169+
if (prevopcode != Instruction::MATCH) had_incomplete_match = false;
170+
if (matchlen < 8 && had_incomplete_match) return false; // Within a sequence of matches only at most one should be incomplete
171+
had_incomplete_match = (matchlen < 8);
164172
if (bits < matchlen) return false; // Consuming bits past the end of the input
165173
bits -= matchlen;
174+
prevopcode = Instruction::MATCH;
166175
} else if (opcode == Instruction::DEFAULT) {
176+
if (prevopcode == Instruction::DEFAULT) return false; // There should not be two successive DEFAULTs (they could be combined into one)
167177
uint32_t asn = DecodeASN(pos, endpos);
168178
if (asn == INVALID) return false; // ASN straddles EOF
179+
prevopcode = Instruction::DEFAULT;
169180
} else {
170181
return false; // Instruction straddles EOF
171182
}

0 commit comments

Comments
 (0)