mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 06:52:36 +01:00
Add additional effiency checks to sanity checker
This commit is contained in:
parent
fffd8dca2d
commit
c81aefc537
1 changed files with 11 additions and 0 deletions
|
@ -126,11 +126,14 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
|
||||||
std::vector<bool>::const_iterator pos = begin;
|
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)
|
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);
|
jumps.reserve(bits);
|
||||||
|
Instruction prevopcode = Instruction::JUMP;
|
||||||
|
bool had_incomplete_match = false;
|
||||||
while (pos != endpos) {
|
while (pos != endpos) {
|
||||||
uint32_t offset = pos - begin;
|
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
|
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);
|
Instruction opcode = DecodeType(pos, endpos);
|
||||||
if (opcode == Instruction::RETURN) {
|
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);
|
uint32_t asn = DecodeASN(pos, endpos);
|
||||||
if (asn == INVALID) return false; // ASN straddles EOF
|
if (asn == INVALID) return false; // ASN straddles EOF
|
||||||
if (jumps.empty()) {
|
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
|
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
|
bits = jumps.back().second; // Restore the number of bits we would have had left after this jump
|
||||||
jumps.pop_back();
|
jumps.pop_back();
|
||||||
|
prevopcode = Instruction::JUMP;
|
||||||
}
|
}
|
||||||
} else if (opcode == Instruction::JUMP) {
|
} else if (opcode == Instruction::JUMP) {
|
||||||
uint32_t jump = DecodeJump(pos, endpos);
|
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;
|
uint32_t jump_offset = pos - begin + jump;
|
||||||
if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
|
if (!jumps.empty() && jump_offset >= jumps.back().first) return false; // Intersecting jumps
|
||||||
jumps.emplace_back(jump_offset, bits);
|
jumps.emplace_back(jump_offset, bits);
|
||||||
|
prevopcode = Instruction::JUMP;
|
||||||
} else if (opcode == Instruction::MATCH) {
|
} else if (opcode == Instruction::MATCH) {
|
||||||
uint32_t match = DecodeMatch(pos, endpos);
|
uint32_t match = DecodeMatch(pos, endpos);
|
||||||
if (match == INVALID) return false; // Match bits straddle EOF
|
if (match == INVALID) return false; // Match bits straddle EOF
|
||||||
int matchlen = CountBits(match) - 1;
|
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
|
if (bits < matchlen) return false; // Consuming bits past the end of the input
|
||||||
bits -= matchlen;
|
bits -= matchlen;
|
||||||
|
prevopcode = Instruction::MATCH;
|
||||||
} else if (opcode == Instruction::DEFAULT) {
|
} 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);
|
uint32_t asn = DecodeASN(pos, endpos);
|
||||||
if (asn == INVALID) return false; // ASN straddles EOF
|
if (asn == INVALID) return false; // ASN straddles EOF
|
||||||
|
prevopcode = Instruction::DEFAULT;
|
||||||
} else {
|
} else {
|
||||||
return false; // Instruction straddles EOF
|
return false; // Instruction straddles EOF
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue