diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2020-01-30 16:46:21 -0800 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2020-01-31 14:51:37 -0800 |
commit | c86bc144081f960347232546f7d22deb65d27deb (patch) | |
tree | cab22a1c6604adb9473ee19da0f5a1524e286b2d /src/util | |
parent | 38c2395d7a905c87dc4630031849fd8e403e61bf (diff) |
Make asmap Interpret tolerant of malicious map data
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/asmap.cpp | 42 |
1 files changed, 24 insertions, 18 deletions
diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp index ac230e9ee5..60bd27bf90 100644 --- a/src/util/asmap.cpp +++ b/src/util/asmap.cpp @@ -8,13 +8,14 @@ namespace { -uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes) +uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos, uint8_t minval, const std::vector<uint8_t> &bit_sizes) { uint32_t val = minval; bool bit; for (std::vector<uint8_t>::const_iterator bit_sizes_it = bit_sizes.begin(); bit_sizes_it != bit_sizes.end(); ++bit_sizes_it) { if (bit_sizes_it + 1 != bit_sizes.end()) { + if (bitpos == endpos) break; bit = *bitpos; bitpos++; } else { @@ -24,6 +25,7 @@ uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, c val += (1 << *bit_sizes_it); } else { for (int b = 0; b < *bit_sizes_it; b++) { + if (bitpos == endpos) break; bit = *bitpos; bitpos++; val += bit << (*bit_sizes_it - 1 - b); @@ -35,29 +37,29 @@ uint32_t DecodeBits(std::vector<bool>::const_iterator& bitpos, uint8_t minval, c } const std::vector<uint8_t> TYPE_BIT_SIZES{0, 0, 1}; -uint32_t DecodeType(std::vector<bool>::const_iterator& bitpos) +uint32_t DecodeType(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos) { - return DecodeBits(bitpos, 0, TYPE_BIT_SIZES); + return DecodeBits(bitpos, endpos, 0, TYPE_BIT_SIZES); } const std::vector<uint8_t> ASN_BIT_SIZES{15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; -uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos) +uint32_t DecodeASN(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos) { - return DecodeBits(bitpos, 1, ASN_BIT_SIZES); + return DecodeBits(bitpos, endpos, 1, ASN_BIT_SIZES); } const std::vector<uint8_t> MATCH_BIT_SIZES{1, 2, 3, 4, 5, 6, 7, 8}; -uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos) +uint32_t DecodeMatch(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos) { - return DecodeBits(bitpos, 2, MATCH_BIT_SIZES); + return DecodeBits(bitpos, endpos, 2, MATCH_BIT_SIZES); } const std::vector<uint8_t> JUMP_BIT_SIZES{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}; -uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos) +uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos, const std::vector<bool>::const_iterator& endpos) { - return DecodeBits(bitpos, 17, JUMP_BIT_SIZES); + return DecodeBits(bitpos, endpos, 17, JUMP_BIT_SIZES); } } @@ -65,33 +67,37 @@ uint32_t DecodeJump(std::vector<bool>::const_iterator& bitpos) uint32_t Interpret(const std::vector<bool> &asmap, const std::vector<bool> &ip) { std::vector<bool>::const_iterator pos = asmap.begin(); + const std::vector<bool>::const_iterator endpos = asmap.end(); uint8_t bits = ip.size(); - uint8_t default_asn = 0; + uint32_t default_asn = 0; uint32_t opcode, jump, match, matchlen; - while (1) { - assert(pos != asmap.end()); - opcode = DecodeType(pos); + while (pos != endpos) { + opcode = DecodeType(pos, endpos); if (opcode == 0) { - return DecodeASN(pos); + return DecodeASN(pos, endpos); } else if (opcode == 1) { - jump = DecodeJump(pos); + jump = DecodeJump(pos, endpos); + if (bits == 0) break; if (ip[ip.size() - bits]) { + if (jump >= endpos - pos) break; pos += jump; } bits--; } else if (opcode == 2) { - match = DecodeMatch(pos); + match = DecodeMatch(pos, endpos); matchlen = CountBits(match) - 1; for (uint32_t bit = 0; bit < matchlen; bit++) { + if (bits == 0) break; if ((ip[ip.size() - bits]) != ((match >> (matchlen - 1 - bit)) & 1)) { return default_asn; } bits--; } } else if (opcode == 3) { - default_asn = DecodeASN(pos); + default_asn = DecodeASN(pos, endpos); } else { - assert(0); + break; } } + return 0; // 0 is not a valid ASN } |