_ZN5Botan3fmtIJPKcNSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEEEENS3_12basic_stringIcS6_NS3_9allocatorIcEEEES7_DpRKT_:
   53|    411|std::string fmt(std::string_view format, const T&... args) {
   54|    411|   std::ostringstream oss;
   55|    411|   oss.imbue(std::locale::classic());
   56|    411|   fmt_detail::do_fmt(oss, format, args...);
   57|    411|   return oss.str();
   58|    411|}
_ZN5Botan10fmt_detail6do_fmtIPKcJNSt3__117basic_string_viewIcNS4_11char_traitsIcEEEEEEEvRNS4_19basic_ostringstreamIcS7_NS4_9allocatorIcEEEES8_RKT_DpRKT0_:
   25|    411|void do_fmt(std::ostringstream& oss, std::string_view format, const T& val, const Ts&... rest) {
   26|    411|   size_t i = 0;
   27|       |
   28|  2.46k|   while(i < format.size()) {
  ------------------
  |  Branch (28:10): [True: 2.46k, False: 0]
  ------------------
   29|  2.46k|      if(format[i] == '{' && (format.size() > (i + 1)) && format.at(i + 1) == '}') {
  ------------------
  |  Branch (29:10): [True: 411, False: 2.05k]
  |  Branch (29:30): [True: 411, False: 0]
  |  Branch (29:59): [True: 411, False: 0]
  ------------------
   30|    411|         oss << val;
   31|    411|         return do_fmt(oss, format.substr(i + 2), rest...);
   32|  2.05k|      } else {
   33|  2.05k|         oss << format[i];
   34|  2.05k|      }
   35|       |
   36|  2.05k|      i += 1;
   37|  2.05k|   }
   38|    411|}
_ZN5Botan10fmt_detail6do_fmtINSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEJEEEvRNS2_19basic_ostringstreamIcS5_NS2_9allocatorIcEEEES6_RKT_DpRKT0_:
   25|    703|void do_fmt(std::ostringstream& oss, std::string_view format, const T& val, const Ts&... rest) {
   26|    703|   size_t i = 0;
   27|       |
   28|  18.9k|   while(i < format.size()) {
  ------------------
  |  Branch (28:10): [True: 18.9k, False: 0]
  ------------------
   29|  18.9k|      if(format[i] == '{' && (format.size() > (i + 1)) && format.at(i + 1) == '}') {
  ------------------
  |  Branch (29:10): [True: 703, False: 18.2k]
  |  Branch (29:30): [True: 703, False: 0]
  |  Branch (29:59): [True: 703, False: 0]
  ------------------
   30|    703|         oss << val;
   31|    703|         return do_fmt(oss, format.substr(i + 2), rest...);
   32|  18.2k|      } else {
   33|  18.2k|         oss << format[i];
   34|  18.2k|      }
   35|       |
   36|  18.2k|      i += 1;
   37|  18.2k|   }
   38|    703|}
_ZN5Botan10fmt_detail6do_fmtERNSt3__119basic_ostringstreamIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS1_17basic_string_viewIcS4_EE:
   20|    703|inline void do_fmt(std::ostringstream& oss, std::string_view format) {
   21|    703|   oss << format;
   22|    703|}
_ZN5Botan3fmtIJNSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEEEENS1_12basic_stringIcS4_NS1_9allocatorIcEEEES5_DpRKT_:
   53|    292|std::string fmt(std::string_view format, const T&... args) {
   54|    292|   std::ostringstream oss;
   55|    292|   oss.imbue(std::locale::classic());
   56|    292|   fmt_detail::do_fmt(oss, format, args...);
   57|    292|   return oss.str();
   58|    292|}

_ZN5Botan8get_byteILm0EtEEhT0_QltT_stS1_:
   81|    148|{
   82|    148|   const size_t shift = ((~B) & (sizeof(T) - 1)) << 3;
   83|    148|   return static_cast<uint8_t>((input >> shift) & 0xFF);
   84|    148|}
_ZN5Botan8get_byteILm1EtEEhT0_QltT_stS1_:
   81|    148|{
   82|    148|   const size_t shift = ((~B) & (sizeof(T) - 1)) << 3;
   83|    148|   return static_cast<uint8_t>((input >> shift) & 0xFF);
   84|    148|}

_ZN5Botan3URIC2ENS0_4TypeENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEt:
   30|    159|      URI(Type type, std::string_view host, uint16_t port) : m_type(type), m_host(host), m_port(port) {}

_ZN5Botan11IPv6AddressC2ENSt3__15arrayIhLm16EEE:
   29|     31|      explicit IPv6Address(std::array<uint8_t, 16> ip) : m_ip(ip) {}

LLVMFuzzerInitialize:
   28|      2|extern "C" int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) {
   29|       |   /*
   30|       |   * This disables the mlock pool, as overwrites within the pool are
   31|       |   * opaque to ASan or other instrumentation.
   32|       |   */
   33|      2|   ::setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1);
   34|      2|   return 0;
   35|      2|}
LLVMFuzzerTestOneInput:
   39|    643|extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
   40|    643|   if(len <= max_fuzzer_input_size) {
  ------------------
  |  Branch (40:7): [True: 633, False: 10]
  ------------------
   41|    633|      try {
   42|    633|         fuzz(std::span<const uint8_t>(in, len));
   43|    633|      } catch(const std::exception& e) {
   44|      0|         std::cerr << "Uncaught exception from fuzzer driver " << e.what() << "\n";
   45|      0|         abort();
   46|      0|      } catch(...) {
   47|      0|         std::cerr << "Uncaught exception from fuzzer driver (unknown type)\n";
   48|      0|         abort();
   49|      0|      }
   50|    633|   }
   51|    643|   return 0;
   52|    643|}

_Z4fuzzNSt3__14spanIKhLm18446744073709551615EEE:
   11|    633|void fuzz(std::span<const uint8_t> input) {
   12|    633|   if(input.size() > max_fuzzer_input_size) {
  ------------------
  |  Branch (12:7): [True: 0, False: 633]
  ------------------
   13|      0|      return;
   14|      0|   }
   15|       |
   16|    633|   try {
   17|    633|      Botan::URI::from_any(std::string(reinterpret_cast<const char*>(input.data()), input.size()));
   18|    633|   } catch(const Botan::Exception& e) {}
   19|    633|}

_ZN5Botan9ExceptionC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   71|  1.98k|Exception::Exception(std::string_view msg) : m_msg(msg) {}
_ZN5Botan16Invalid_ArgumentC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   77|  1.69k|Invalid_Argument::Invalid_Argument(std::string_view msg) : Exception(msg) {}
_ZN5Botan14Decoding_ErrorC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  125|    292|Decoding_Error::Decoding_Error(std::string_view name) : Exception(name) {}

_ZN5Botan11IPv6Address11from_stringENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   23|    543|std::optional<IPv6Address> IPv6Address::from_string(std::string_view str) {
   24|    543|   if(str.empty()) {
  ------------------
  |  Branch (24:7): [True: 16, False: 527]
  ------------------
   25|     16|      return {};
   26|     16|   }
   27|       |
   28|       |   // Parsed hex groups, split by whether they appeared before or after a "::".
   29|       |   // If no "::" appears, only `pre` is populated and must reach exactly 8 groups.
   30|    527|   std::array<uint16_t, 8> pre{};
   31|    527|   std::array<uint16_t, 8> post{};
   32|    527|   size_t pre_count = 0;
   33|    527|   size_t post_count = 0;
   34|    527|   bool seen_double_colon = false;
   35|       |
   36|    527|   auto hex_value = [](char c) -> std::optional<uint8_t> {
   37|    527|      if(c >= '0' && c <= '9') {
   38|    527|         return c - '0';
   39|    527|      } else if(c >= 'a' && c <= 'f') {
   40|    527|         return 10 + (c - 'a');
   41|    527|      } else if(c >= 'A' && c <= 'F') {
   42|    527|         return 10 + (c - 'A');
   43|    527|      } else {
   44|    527|         return {};
   45|    527|      }
   46|    527|   };
   47|       |
   48|    527|   size_t idx = 0;
   49|    527|   bool expect_group = true;  // set after any separator, cleared after a group
   50|       |
   51|  2.37k|   while(idx < str.size()) {
  ------------------
  |  Branch (51:10): [True: 2.29k, False: 83]
  ------------------
   52|  2.29k|      if(str[idx] == ':') {
  ------------------
  |  Branch (52:10): [True: 893, False: 1.40k]
  ------------------
   53|    893|         if(idx + 1 < str.size() && str[idx + 1] == ':') {
  ------------------
  |  Branch (53:13): [True: 881, False: 12]
  |  Branch (53:37): [True: 80, False: 801]
  ------------------
   54|     80|            if(seen_double_colon) {
  ------------------
  |  Branch (54:16): [True: 5, False: 75]
  ------------------
   55|      5|               return {};  // at most one "::"
   56|      5|            }
   57|     75|            seen_double_colon = true;
   58|     75|            idx += 2;
   59|     75|            expect_group = (idx < str.size());
   60|     75|            continue;
   61|     80|         }
   62|       |         // single ':' separator between groups, only valid after a group
   63|    813|         if(expect_group) {
  ------------------
  |  Branch (63:13): [True: 64, False: 749]
  ------------------
   64|     64|            return {};
   65|     64|         }
   66|    749|         expect_group = true;
   67|    749|         idx += 1;
   68|    749|         continue;
   69|    813|      }
   70|       |
   71|       |      // Parse a hex group of 1..4 digits
   72|  1.40k|      uint32_t group = 0;
   73|  1.40k|      size_t hex_chars = 0;
   74|  4.50k|      while(idx < str.size() && hex_chars < 4) {
  ------------------
  |  Branch (74:13): [True: 4.43k, False: 66]
  |  Branch (74:33): [True: 3.87k, False: 567]
  ------------------
   75|  3.87k|         const auto digit = hex_value(str[idx]);
   76|  3.87k|         if(digit.has_value() == false) {
  ------------------
  |  Branch (76:13): [True: 769, False: 3.10k]
  ------------------
   77|    769|            break;
   78|    769|         }
   79|  3.10k|         group = (group << 4) | static_cast<uint32_t>(digit.value());
   80|  3.10k|         idx += 1;
   81|  3.10k|         hex_chars += 1;
   82|  3.10k|      }
   83|  1.40k|      if(hex_chars == 0) {
  ------------------
  |  Branch (83:10): [True: 301, False: 1.10k]
  ------------------
   84|    301|         return {};
   85|    301|      }
   86|       |      // If a 5th hex digit follows, the group is oversized.
   87|  1.10k|      if(hex_chars == 4 && idx < str.size() && hex_value(str[idx]).has_value()) {
  ------------------
  |  Branch (87:10): [True: 582, False: 519]
  |  Branch (87:10): [True: 57, False: 1.04k]
  |  Branch (87:28): [True: 567, False: 15]
  |  Branch (87:48): [True: 57, False: 510]
  ------------------
   88|     57|         return {};
   89|     57|      }
   90|       |
   91|  1.04k|      if(seen_double_colon) {
  ------------------
  |  Branch (91:10): [True: 306, False: 738]
  ------------------
   92|    306|         if(post_count >= 8) {
  ------------------
  |  Branch (92:13): [True: 15, False: 291]
  ------------------
   93|     15|            return {};
   94|     15|         }
   95|    291|         post[post_count++] = static_cast<uint16_t>(group);
   96|    738|      } else {
   97|    738|         if(pre_count >= 8) {
  ------------------
  |  Branch (97:13): [True: 2, False: 736]
  ------------------
   98|      2|            return {};
   99|      2|         }
  100|    736|         pre[pre_count++] = static_cast<uint16_t>(group);
  101|    736|      }
  102|  1.02k|      expect_group = false;
  103|  1.02k|   }
  104|       |
  105|       |   // Trailing single ':' is invalid
  106|     83|   if(expect_group) {
  ------------------
  |  Branch (106:7): [True: 9, False: 74]
  ------------------
  107|      9|      return {};
  108|      9|   }
  109|       |
  110|     74|   const size_t total_groups = pre_count + post_count;
  111|     74|   if(seen_double_colon) {
  ------------------
  |  Branch (111:7): [True: 31, False: 43]
  ------------------
  112|       |      // "::" has to cover at least one zero group
  113|     31|      if(total_groups > 7) {
  ------------------
  |  Branch (113:10): [True: 7, False: 24]
  ------------------
  114|      7|         return {};
  115|      7|      }
  116|     43|   } else {
  117|     43|      if(total_groups != 8) {
  ------------------
  |  Branch (117:10): [True: 36, False: 7]
  ------------------
  118|     36|         return {};
  119|     36|      }
  120|     43|   }
  121|       |
  122|     31|   std::array<uint8_t, 16> out{};
  123|    141|   for(size_t i = 0; i != pre_count; ++i) {
  ------------------
  |  Branch (123:22): [True: 110, False: 31]
  ------------------
  124|    110|      out[2 * i] = get_byte<0>(pre[i]);
  125|    110|      out[2 * i + 1] = get_byte<1>(pre[i]);
  126|    110|   }
  127|     31|   const size_t gap = 8 - total_groups;
  128|     69|   for(size_t i = 0; i != post_count; ++i) {
  ------------------
  |  Branch (128:22): [True: 38, False: 31]
  ------------------
  129|     38|      const size_t target = pre_count + gap + i;
  130|     38|      out[2 * target] = get_byte<0>(post[i]);
  131|     38|      out[2 * target + 1] = get_byte<1>(post[i]);
  132|     38|   }
  133|     31|   return IPv6Address(out);
  134|     74|}
ipv6_address.cpp:_ZZN5Botan11IPv6Address11from_stringENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEEENK3$_0clEc:
   36|  4.43k|   auto hex_value = [](char c) -> std::optional<uint8_t> {
   37|  4.43k|      if(c >= '0' && c <= '9') {
  ------------------
  |  Branch (37:10): [True: 4.10k, False: 339]
  |  Branch (37:22): [True: 1.47k, False: 2.62k]
  ------------------
   38|  1.47k|         return c - '0';
   39|  2.96k|      } else if(c >= 'a' && c <= 'f') {
  ------------------
  |  Branch (39:17): [True: 674, False: 2.29k]
  |  Branch (39:29): [True: 626, False: 48]
  ------------------
   40|    626|         return 10 + (c - 'a');
   41|  2.34k|      } else if(c >= 'A' && c <= 'F') {
  ------------------
  |  Branch (41:17): [True: 1.16k, False: 1.18k]
  |  Branch (41:29): [True: 1.06k, False: 97]
  ------------------
   42|  1.06k|         return 10 + (c - 'A');
   43|  1.27k|      } else {
   44|  1.27k|         return {};
   45|  1.27k|      }
   46|  4.43k|   };

_ZN5Botan14string_to_ipv4ENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEE:
  154|    833|std::optional<uint32_t> string_to_ipv4(std::string_view str) {
  155|       |   // At least 3 dots + 4 1-digit integers
  156|       |   // At most 3 dots + 4 3-digit integers
  157|    833|   if(str.size() < 3 + 4 * 1 || str.size() > 3 + 4 * 3) {
  ------------------
  |  Branch (157:7): [True: 432, False: 401]
  |  Branch (157:33): [True: 282, False: 119]
  ------------------
  158|    714|      return {};
  159|    714|   }
  160|       |
  161|       |   // the final result
  162|    119|   uint32_t ip = 0;
  163|       |   // the number of '.' seen so far
  164|    119|   size_t dots = 0;
  165|       |   // accumulates one quad (range 0-255)
  166|    119|   uint32_t accum = 0;
  167|       |   // # of digits pushed to accum since last dot
  168|    119|   size_t cur_digits = 0;
  169|       |
  170|    483|   for(const char c : str) {
  ------------------
  |  Branch (170:21): [True: 483, False: 17]
  ------------------
  171|    483|      if(c == '.') {
  ------------------
  |  Branch (171:10): [True: 99, False: 384]
  ------------------
  172|       |         // . without preceding digit is invalid
  173|     99|         if(cur_digits == 0) {
  ------------------
  |  Branch (173:13): [True: 2, False: 97]
  ------------------
  174|      2|            return {};
  175|      2|         }
  176|     97|         dots += 1;
  177|       |         // too many dots
  178|     97|         if(dots > 3) {
  ------------------
  |  Branch (178:13): [True: 4, False: 93]
  ------------------
  179|      4|            return {};
  180|      4|         }
  181|       |
  182|     93|         cur_digits = 0;
  183|     93|         ip = (ip << 8) | accum;
  184|     93|         accum = 0;
  185|    384|      } else if(c >= '0' && c <= '9') {
  ------------------
  |  Branch (185:17): [True: 348, False: 36]
  |  Branch (185:29): [True: 322, False: 26]
  ------------------
  186|    322|         const auto d = static_cast<uint8_t>(c - '0');
  187|       |
  188|       |         // prohibit leading zero in quad (used for octal)
  189|    322|         if(cur_digits > 0 && accum == 0) {
  ------------------
  |  Branch (189:13): [True: 160, False: 162]
  |  Branch (189:31): [True: 10, False: 150]
  ------------------
  190|     10|            return {};
  191|     10|         }
  192|    312|         accum = (accum * 10) + d;
  193|       |
  194|    312|         if(accum > 255) {
  ------------------
  |  Branch (194:13): [True: 24, False: 288]
  ------------------
  195|     24|            return {};
  196|     24|         }
  197|       |
  198|    288|         cur_digits++;
  199|    288|         BOTAN_ASSERT_NOMSG(cur_digits <= 3);
  ------------------
  |  |   77|    288|   do {                                                                     \
  |  |   78|    288|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   79|    288|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (79:10): [True: 0, False: 288]
  |  |  ------------------
  |  |   80|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   81|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   82|      0|      }                                                                     \
  |  |   83|    288|   } while(0)
  |  |  ------------------
  |  |  |  Branch (83:12): [Folded, False: 288]
  |  |  ------------------
  ------------------
  200|    288|      } else {
  201|     62|         return {};
  202|     62|      }
  203|    483|   }
  204|       |
  205|       |   // no trailing digits?
  206|     17|   if(cur_digits == 0) {
  ------------------
  |  Branch (206:7): [True: 2, False: 15]
  ------------------
  207|      2|      return {};
  208|      2|   }
  209|       |
  210|       |   // insufficient # of dots
  211|     15|   if(dots != 3) {
  ------------------
  |  Branch (211:7): [True: 8, False: 7]
  ------------------
  212|      8|      return {};
  213|      8|   }
  214|       |
  215|      7|   ip = (ip << 8) | accum;
  216|       |
  217|      7|   return ip;
  218|     15|}
_ZN5Botan31check_and_canonicalize_dns_nameENSt3__117basic_string_viewIcNS0_11char_traitsIcEEEE:
  393|    413|std::string check_and_canonicalize_dns_name(std::string_view name) {
  394|    413|   if(name.size() > 255) {
  ------------------
  |  Branch (394:7): [True: 66, False: 347]
  ------------------
  395|     66|      throw Decoding_Error("DNS name exceeds maximum allowed length");
  396|     66|   }
  397|       |
  398|    347|   if(name.empty()) {
  ------------------
  |  Branch (398:7): [True: 37, False: 310]
  ------------------
  399|     37|      throw Decoding_Error("DNS name cannot be empty");
  400|     37|   }
  401|       |
  402|    310|   if(name.starts_with(".") || name.ends_with(".")) {
  ------------------
  |  Branch (402:7): [True: 1, False: 309]
  |  Branch (402:32): [True: 6, False: 303]
  ------------------
  403|      7|      throw Decoding_Error("DNS name cannot start or end with a dot");
  404|      7|   }
  405|       |
  406|       |   /*
  407|       |   * Table mapping uppercase to lowercase and only including values for valid DNS names
  408|       |   * namely A-Z, a-z, 0-9, hyphen, and dot, plus '*' for wildcarding. (RFC 1035)
  409|       |   */
  410|       |   // clang-format off
  411|    303|   constexpr uint8_t DNS_CHAR_MAPPING[128] = {
  412|    303|      '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
  413|    303|      '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
  414|    303|      '\0', '\0', '\0', '\0',  '*', '\0', '\0',  '-',  '.', '\0',  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',
  415|    303|       '9', '\0', '\0', '\0', '\0', '\0', '\0', '\0',  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',
  416|    303|       'l',  'm',  'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z', '\0', '\0', '\0', '\0',
  417|    303|      '\0', '\0',  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',  'p',  'q',
  418|    303|       'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z', '\0', '\0', '\0', '\0', '\0',
  419|    303|   };
  420|       |   // clang-format on
  421|       |
  422|    303|   std::string canon;
  423|    303|   canon.reserve(name.size());
  424|       |
  425|       |   // RFC 1035: DNS labels must not exceed 63 characters
  426|    303|   size_t current_label_length = 0;
  427|       |
  428|  4.12k|   for(size_t i = 0; i != name.size(); ++i) {
  ------------------
  |  Branch (428:22): [True: 3.99k, False: 121]
  ------------------
  429|  3.99k|      const char c = name[i];
  430|       |
  431|  3.99k|      if(c == '.') {
  ------------------
  |  Branch (431:10): [True: 541, False: 3.45k]
  ------------------
  432|    541|         if(i > 0 && name[i - 1] == '.') {
  ------------------
  |  Branch (432:13): [True: 541, False: 0]
  |  Branch (432:22): [True: 2, False: 539]
  ------------------
  433|      2|            throw Decoding_Error("DNS name contains sequential period chars");
  434|      2|         }
  435|       |
  436|    539|         if(current_label_length == 0) {
  ------------------
  |  Branch (436:13): [True: 0, False: 539]
  ------------------
  437|      0|            throw Decoding_Error("DNS name contains empty label");
  438|      0|         }
  439|    539|         current_label_length = 0;  // Reset for next label
  440|  3.45k|      } else {
  441|  3.45k|         current_label_length++;
  442|       |
  443|  3.45k|         if(current_label_length > 63) {  // RFC 1035 Maximum DNS label length
  ------------------
  |  Branch (443:13): [True: 2, False: 3.45k]
  ------------------
  444|      2|            throw Decoding_Error("DNS name label exceeds maximum length of 63 characters");
  445|      2|         }
  446|  3.45k|      }
  447|       |
  448|  3.99k|      const uint8_t cu = static_cast<uint8_t>(c);
  449|  3.99k|      if(cu >= 128) {
  ------------------
  |  Branch (449:10): [True: 32, False: 3.96k]
  ------------------
  450|     32|         throw Decoding_Error("DNS name must not contain any extended ASCII code points");
  451|     32|      }
  452|  3.96k|      const uint8_t mapped = DNS_CHAR_MAPPING[cu];
  453|  3.96k|      if(mapped == 0) {
  ------------------
  |  Branch (453:10): [True: 117, False: 3.84k]
  ------------------
  454|    117|         throw Decoding_Error("DNS name includes invalid character");
  455|    117|      }
  456|       |
  457|  3.84k|      if(mapped == '-') {
  ------------------
  |  Branch (457:10): [True: 624, False: 3.22k]
  ------------------
  458|    624|         if(i == 0 || (i > 0 && name[i - 1] == '.')) {
  ------------------
  |  Branch (458:13): [True: 4, False: 620]
  |  Branch (458:24): [True: 620, False: 0]
  |  Branch (458:33): [True: 3, False: 617]
  ------------------
  459|      7|            throw Decoding_Error("DNS name has label with leading hyphen");
  460|    617|         } else if(i == name.size() - 1 || (i < name.size() - 1 && name[i + 1] == '.')) {
  ------------------
  |  Branch (460:20): [True: 21, False: 596]
  |  Branch (460:45): [True: 596, False: 0]
  |  Branch (460:68): [True: 1, False: 595]
  ------------------
  461|     22|            throw Decoding_Error("DNS name has label with trailing hyphen");
  462|     22|         }
  463|    624|      }
  464|  3.81k|      canon.push_back(static_cast<char>(mapped));
  465|  3.81k|   }
  466|       |
  467|    121|   if(current_label_length == 0) {
  ------------------
  |  Branch (467:7): [True: 0, False: 121]
  ------------------
  468|      0|      throw Decoding_Error("DNS name contains empty label");
  469|      0|   }
  470|    121|   return canon;
  471|    121|}

_ZN5Botan3URI11from_domainENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   73|    595|URI URI::from_domain(std::string_view uri) {
   74|    595|   BOTAN_ARG_CHECK(!uri.empty(), "URI::from_domain empty URI is invalid");
  ------------------
  |  |   35|    595|   do {                                                          \
  |  |   36|    595|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    595|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 595]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    595|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 595]
  |  |  ------------------
  ------------------
   75|       |
   76|    595|   uint16_t port = 0;
   77|    595|   const auto port_pos = uri.find(':');
   78|    595|   if(port_pos != std::string::npos) {
  ------------------
  |  Branch (78:7): [True: 263, False: 332]
  ------------------
   79|    263|      port = parse_port_number("from_domain", uri, port_pos);
   80|    263|   }
   81|    595|   const auto domain = uri.substr(0, port_pos);
   82|    595|   if(is_ipv4(domain)) {
  ------------------
  |  Branch (82:7): [True: 0, False: 595]
  ------------------
   83|      0|      throw Invalid_Argument("URI::from_domain domain name should not be IP address");
   84|      0|   }
   85|    595|   if(!is_domain_name(domain)) {
  ------------------
  |  Branch (85:7): [True: 292, False: 303]
  ------------------
   86|    292|      throw Invalid_Argument(fmt("URI::from_domain domain name '{}' not valid", domain));
   87|    292|   }
   88|       |
   89|    303|   return URI(Type::Domain, domain, port);
   90|    595|}
_ZN5Botan3URI9from_ipv4ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   92|    633|URI URI::from_ipv4(std::string_view uri) {
   93|    633|   BOTAN_ARG_CHECK(!uri.empty(), "URI::from_ipv4 empty URI is invalid");
  ------------------
  |  |   35|    633|   do {                                                          \
  |  |   36|    633|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    633|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 633]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    633|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 633]
  |  |  ------------------
  ------------------
   94|       |
   95|    633|   const auto port_pos = uri.find(':');
   96|    633|   const uint16_t port = parse_port_number("from_ipv4", uri, port_pos);
   97|    633|   const auto ip = uri.substr(0, port_pos);
   98|    633|   if(!is_ipv4(ip)) {
  ------------------
  |  Branch (98:7): [True: 413, False: 220]
  ------------------
   99|    413|      throw Invalid_Argument("URI::from_ipv4: Invalid IPv4 specifier");
  100|    413|   }
  101|    220|   return URI(Type::IPv4, ip, port);
  102|    633|}
_ZN5Botan3URI9from_ipv6ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  104|    626|URI URI::from_ipv6(std::string_view uri) {
  105|    626|   BOTAN_ARG_CHECK(!uri.empty(), "URI::from_ipv6 empty URI is invalid");
  ------------------
  |  |   35|    626|   do {                                                          \
  |  |   36|    626|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    626|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 626]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    626|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 626]
  |  |  ------------------
  ------------------
  106|       |
  107|    626|   const auto port_pos = uri.find(']');
  108|    626|   const bool with_braces = (port_pos != std::string::npos);
  109|    626|   if((uri[0] == '[') != with_braces) {
  ------------------
  |  Branch (109:7): [True: 37, False: 589]
  ------------------
  110|     37|      throw Invalid_Argument("URI::from_ipv6 Invalid IPv6 address with mismatch braces");
  111|     37|   }
  112|       |
  113|    589|   uint16_t port = 0;
  114|    589|   if(with_braces && (uri.size() > port_pos + 1)) {
  ------------------
  |  Branch (114:7): [True: 118, False: 471]
  |  Branch (114:22): [True: 84, False: 34]
  ------------------
  115|     84|      if(uri[port_pos + 1] != ':') {
  ------------------
  |  Branch (115:10): [True: 30, False: 54]
  ------------------
  116|     30|         throw Invalid_Argument("URI::from_ipv6 Invalid IPv6 address");
  117|     30|      }
  118|       |
  119|     54|      port = parse_port_number("from_ipv6", uri, port_pos + 1);
  120|     54|   }
  121|    559|   const auto ip = with_braces ? uri.substr(1, port_pos - 1) : uri.substr(0, port_pos);
  ------------------
  |  Branch (121:20): [True: 72, False: 487]
  ------------------
  122|       |
  123|    559|   if(!is_ipv6(ip)) {
  ------------------
  |  Branch (123:7): [True: 512, False: 47]
  ------------------
  124|    512|      throw Invalid_Argument("URI::from_ipv6 URI has invalid IPv6 address");
  125|    512|   }
  126|     47|   return URI(Type::IPv6, ip, port);
  127|    559|}
_ZN5Botan3URI8from_anyENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  129|    633|URI URI::from_any(std::string_view uri) {
  130|    633|   BOTAN_ARG_CHECK(!uri.empty(), "URI::from_any empty URI is invalid");
  ------------------
  |  |   35|    633|   do {                                                          \
  |  |   36|    633|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    633|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 633]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    633|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 633]
  |  |  ------------------
  ------------------
  131|       |
  132|    633|   try {
  133|    633|      return URI::from_ipv4(uri);
  134|    633|   } catch(Invalid_Argument&) {}
  135|       |
  136|    626|   try {
  137|    626|      return URI::from_ipv6(uri);
  138|    626|   } catch(Invalid_Argument&) {}
  139|       |
  140|    595|   return URI::from_domain(uri);
  141|    626|}
uri.cpp:_ZN5Botan12_GLOBAL__N_117parse_port_numberEPKcNSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEm:
   48|    950|uint16_t parse_port_number(const char* func_name, std::string_view uri, size_t pos) {
   49|    950|   if(pos == std::string::npos || uri.empty()) {
  ------------------
  |  Branch (49:7): [True: 338, False: 612]
  |  Branch (49:35): [True: 0, False: 612]
  ------------------
   50|    338|      return 0;
   51|    338|   }
   52|       |
   53|    612|   BOTAN_ARG_CHECK(pos < uri.size(), "URI invalid port specifier");
  ------------------
  |  |   35|    612|   do {                                                          \
  |  |   36|    612|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    612|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 612]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    612|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 612]
  |  |  ------------------
  ------------------
   54|       |
   55|    612|   uint32_t port = 0;
   56|       |
   57|  39.7k|   for(const char c : uri.substr(pos + 1)) {
  ------------------
  |  Branch (57:21): [True: 39.7k, False: 201]
  ------------------
   58|  39.7k|      const size_t digit = c - '0';
   59|  39.7k|      if(digit >= 10) {
  ------------------
  |  Branch (59:10): [True: 383, False: 39.3k]
  ------------------
   60|    383|         throw Invalid_Argument(fmt("URI::{} invalid port field in {}", func_name, uri));
   61|    383|      }
   62|  39.3k|      port = port * 10 + (c - '0');
   63|  39.3k|      if(port > 65535) {
  ------------------
  |  Branch (63:10): [True: 28, False: 39.3k]
  ------------------
   64|     28|         throw Invalid_Argument(fmt("URI::{} invalid port field in {}", func_name, uri));
   65|     28|      }
   66|  39.3k|   }
   67|       |
   68|    201|   return static_cast<uint16_t>(port);
   69|    612|}
uri.cpp:_ZN5Botan12_GLOBAL__N_17is_ipv4ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   40|    833|bool is_ipv4(std::string_view ip) {
   41|    833|   return string_to_ipv4(ip).has_value();
   42|    833|}
uri.cpp:_ZN5Botan12_GLOBAL__N_114is_domain_nameENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   31|    413|bool is_domain_name(std::string_view domain) {
   32|    413|   try {
   33|    413|      check_and_canonicalize_dns_name(domain);
   34|    413|      return true;
   35|    413|   } catch(Decoding_Error&) {
   36|    292|      return false;
   37|    292|   }
   38|    413|}
uri.cpp:_ZN5Botan12_GLOBAL__N_17is_ipv6ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   44|    543|bool is_ipv6(std::string_view ip) {
   45|    543|   return IPv6Address::from_string(ip).has_value();
   46|    543|}

