_ZN5Botan13ignore_paramsIJRhEEEvDpOT_:
  114|    148|void ignore_params(T&&... args) {
  115|    148|   (ignore_param(args), ...);
  116|    148|}
_ZN5Botan12ignore_paramIRhEEvOT_:
  111|    148|void ignore_param(T&&) {}
_ZN5Botan13ignore_paramsIJRPKhRmEEEvDpOT_:
  114|    444|void ignore_params(T&&... args) {
  115|    444|   (ignore_param(args), ...);
  116|    444|}
_ZN5Botan12ignore_paramIRPKhEEvOT_:
  111|    444|void ignore_param(T&&) {}
_ZN5Botan12ignore_paramIRmEEvOT_:
  111|    592|void ignore_param(T&&) {}
_ZN5Botan13ignore_paramsIJRPKmRmEEEvDpOT_:
  114|    148|void ignore_params(T&&... args) {
  115|    148|   (ignore_param(args), ...);
  116|    148|}
_ZN5Botan12ignore_paramIRPKmEEvOT_:
  111|    148|void ignore_param(T&&) {}
_ZN5Botan13ignore_paramsIJRKmEEEvDpOT_:
  114|    148|void ignore_params(T&&... args) {
  115|    148|   (ignore_param(args), ...);
  116|    148|}
_ZN5Botan12ignore_paramIRKmEEvOT_:
  111|    148|void ignore_param(T&&) {}

_ZN5Botan14expand_top_bitIhEET_S1_:
   25|   368k|{
   26|   368k|   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
   27|   368k|}
_ZN5Botan10ct_is_zeroIhEET_S1_:
   35|   368k|{
   36|   368k|   return expand_top_bit<T>(~x & (x - 1));
   37|   368k|}
_ZN5Botan10ct_is_zeroImEET_S1_:
   35|   545M|{
   36|   545M|   return expand_top_bit<T>(~x & (x - 1));
   37|   545M|}
_ZN5Botan14expand_top_bitImEET_S1_:
   25|   545M|{
   26|   545M|   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
   27|   545M|}
_ZN5Botan6chooseImEET_S1_S1_S1_:
  168|    148|inline constexpr T choose(T mask, T a, T b) {
  169|       |   //return (mask & a) | (~mask & b);
  170|    148|   return (b ^ (mask & (a ^ b)));
  171|    148|}

_ZN5Botan2CT4MaskIhEC2Eh:
  279|  1.10M|      Mask(T m) : m_mask(m) {}
_ZNK5Botan2CT4MaskIhE5valueEv:
  276|  1.65M|      T value() const { return m_mask; }
_ZNK5Botan2CT4MaskIhEcoEv:
  213|   184k|      Mask<T> operator~() const { return Mask<T>(~value()); }
_ZN5Botan2CT4MaskIhE7is_zeroEh:
  123|   368k|      static Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(x)); }
_ZNK5Botan2CT4MaskIhE16unpoisoned_valueEv:
  262|    148|      T unpoisoned_value() const {
  263|    148|         T r = value();
  264|    148|         CT::unpoison(r);
  265|    148|         return r;
  266|    148|      }
_ZN5Botan2CT8unpoisonIhEEvRT_:
   66|    148|inline void unpoison(T& p) {
   67|       |#if defined(BOTAN_HAS_VALGRIND)
   68|       |   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
   69|       |#else
   70|    148|   BOTAN_UNUSED(p);
  ------------------
  |  |  118|    148|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   71|    148|#endif
   72|    148|}
_ZN5Botan2CT6poisonIhEEvPKT_m:
   48|    148|inline void poison(const T* p, size_t n) {
   49|       |#if defined(BOTAN_HAS_VALGRIND)
   50|       |   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
   51|       |#else
   52|    148|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  118|    148|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   53|    148|#endif
   54|    148|}
_ZN5Botan2CT4MaskIhE3setEv:
   99|    148|      static Mask<T> set() { return Mask<T>(static_cast<T>(~0)); }
_ZN5Botan2CT4MaskIhE7clearedEv:
  104|    148|      static Mask<T> cleared() { return Mask<T>(0); }
_ZN5Botan2CT4MaskIhE8is_equalEhh:
  128|   184k|      static Mask<T> is_equal(T x, T y) { return Mask<T>::is_zero(static_cast<T>(x ^ y)); }
_ZN5Botan2CTanENS0_4MaskIhEES2_:
  198|   368k|      friend Mask<T> operator&(Mask<T> x, Mask<T> y) { return Mask<T>(x.value() & y.value()); }
_ZN5Botan2CTorENS0_4MaskIhEES2_:
  208|   184k|      friend Mask<T> operator|(Mask<T> x, Mask<T> y) { return Mask<T>(x.value() | y.value()); }
_ZN5Botan2CT4MaskIhEoRES2_:
  190|   184k|      Mask<T>& operator|=(Mask<T> o) {
  191|   184k|         m_mask |= o.value();
  192|   184k|         return (*this);
  193|   184k|      }
_ZNK5Botan2CT4MaskIhE13if_set_returnEh:
  218|   184k|      T if_set_return(T x) const { return m_mask & x; }
_ZN5Botan2CT4MaskIhEaNES2_:
  174|   184k|      Mask<T>& operator&=(Mask<T> o) {
  175|   184k|         m_mask &= o.value();
  176|   184k|         return (*this);
  177|   184k|      }
_ZN5Botan2CT8unpoisonIhEEvPKT_m:
   57|    296|inline void unpoison(const T* p, size_t n) {
   58|       |#if defined(BOTAN_HAS_VALGRIND)
   59|       |   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
   60|       |#else
   61|    296|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  118|    296|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   62|    296|#endif
   63|    296|}
_ZN5Botan2CT6poisonImEEvPKT_m:
   48|    148|inline void poison(const T* p, size_t n) {
   49|       |#if defined(BOTAN_HAS_VALGRIND)
   50|       |   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
   51|       |#else
   52|    148|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  118|    148|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   53|    148|#endif
   54|    148|}
_ZN5Botan2CT4MaskImE6expandIhEES2_NS1_IT_EE:
  115|    148|      static Mask<T> expand(Mask<U> m) {
  116|    148|         static_assert(sizeof(U) < sizeof(T), "sizes ok");
  117|    148|         return ~Mask<T>::is_zero(m.value());
  118|    148|      }
_ZN5Botan2CT4MaskImE7is_zeroEm:
  123|   545M|      static Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(x)); }
_ZN5Botan2CT4MaskImEC2Em:
  279|   545M|      Mask(T m) : m_mask(m) {}
_ZNK5Botan2CT4MaskImEcoEv:
  213|    148|      Mask<T> operator~() const { return Mask<T>(~value()); }
_ZNK5Botan2CT4MaskImE5valueEv:
  276|    444|      T value() const { return m_mask; }
_ZN5Botan2CT4MaskImE5is_gtEmm:
  138|    148|      static Mask<T> is_gt(T x, T y) { return Mask<T>::is_lt(y, x); }
_ZN5Botan2CT4MaskImE5is_ltEmm:
  133|    148|      static Mask<T> is_lt(T x, T y) { return Mask<T>(expand_top_bit<T>(x ^ ((x ^ y) | ((x - y) ^ x)))); }
_ZN5Botan2CT4MaskImEoRES2_:
  190|    148|      Mask<T>& operator|=(Mask<T> o) {
  191|    148|         m_mask |= o.value();
  192|    148|         return (*this);
  193|    148|      }
_ZNK5Botan2CT4MaskImE6selectEmm:
  228|    148|      T select(T x, T y) const { return choose(value(), x, y); }
_ZN5Botan2CT4MaskImE8is_equalEmm:
  128|   545M|      static Mask<T> is_equal(T x, T y) { return Mask<T>::is_zero(static_cast<T>(x ^ y)); }
_ZNK5Botan2CT4MaskImE13if_set_returnEm:
  218|   545M|      T if_set_return(T x) const { return m_mask & x; }
_ZN5Botan2CT8unpoisonIKmEEvRT_:
   66|    148|inline void unpoison(T& p) {
   67|       |#if defined(BOTAN_HAS_VALGRIND)
   68|       |   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
   69|       |#else
   70|    148|   BOTAN_UNUSED(p);
  ------------------
  |  |  118|    148|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   71|    148|#endif
   72|    148|}

_ZN5Botan11checked_mulEmm:
   47|    194|inline std::optional<size_t> checked_mul(size_t x, size_t y) {
   48|    194|#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_add_overflow)
   49|    194|   size_t z;
   50|    194|   if(__builtin_mul_overflow(x, y, &z)) [[unlikely]]
  ------------------
  |  Branch (50:7): [True: 0, False: 194]
  ------------------
   51|       |#elif defined(_MSC_VER)
   52|       |   size_t z;
   53|       |   if(SizeTMult(x, y, &z) != S_OK) [[unlikely]]
   54|       |#else
   55|       |   size_t z = x * y;
   56|       |   if(y && z / y != x) [[unlikely]]
   57|       |#endif
   58|      0|   {
   59|      0|      return std::nullopt;
   60|      0|   }
   61|    194|   return z;
   62|    194|}

_ZN5Botan16secure_allocatorIhE8allocateEm:
   45|    194|      T* allocate(std::size_t n) { return static_cast<T*>(allocate_memory(n, sizeof(T))); }
_ZN5Botan16secure_allocatorIhE10deallocateEPhm:
   47|    194|      void deallocate(T* p, std::size_t n) { deallocate_memory(p, n, sizeof(T)); }

LLVMFuzzerInitialize:
   24|      2|extern "C" int LLVMFuzzerInitialize(int*, char***) {
   25|       |   /*
   26|       |   * This disables the mlock pool, as overwrites within the pool are
   27|       |   * opaque to ASan or other instrumentation.
   28|       |   */
   29|      2|   ::setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1);
   30|      2|   return 0;
   31|      2|}
LLVMFuzzerTestOneInput:
   34|    164|extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
   35|    164|   if(len <= max_fuzzer_input_size) {
  ------------------
  |  Branch (35:7): [True: 154, False: 10]
  ------------------
   36|    154|      fuzz(in, len);
   37|    154|   }
   38|    164|   return 0;
   39|    164|}

_Z4fuzzPKhm:
   54|    154|void fuzz(const uint8_t in[], size_t len) {
   55|    154|   static const Botan::secure_vector<uint8_t> Phash = {1, 2, 3, 4};
   56|       |
   57|    154|   uint8_t lib_valid_mask = 0;
   58|    154|   const Botan::secure_vector<uint8_t> lib_output = Botan::oaep_find_delim(lib_valid_mask, in, len, Phash);
   59|    154|   FUZZER_ASSERT_TRUE(lib_valid_mask == 0 || lib_valid_mask == 0xFF);
  ------------------
  |  |   65|    154|   do {                                                               \
  |  |   66|    201|      if(!(e)) {                                                      \
  |  |  ------------------
  |  |  |  Branch (66:12): [True: 107, False: 47]
  |  |  |  Branch (66:12): [True: 47, False: 0]
  |  |  ------------------
  |  |   67|      0|         FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \
  |  |  ------------------
  |  |  |  |   52|      0|   do {                                                                          \
  |  |  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |  |  |   54|      0|      abort();                                                                   \
  |  |  |  |   55|      0|   } while(0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   68|      0|      }                                                               \
  |  |   69|    154|   } while(0)
  |  |  ------------------
  |  |  |  Branch (69:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   60|       |
   61|    154|   uint8_t ref_valid_mask = 0;
   62|    154|   const Botan::secure_vector<uint8_t> ref_output = ref_oaep_unpad(ref_valid_mask, in, len, Phash);
   63|    154|   FUZZER_ASSERT_TRUE(ref_valid_mask == 0 || ref_valid_mask == 0xFF);
  ------------------
  |  |   65|    154|   do {                                                               \
  |  |   66|    201|      if(!(e)) {                                                      \
  |  |  ------------------
  |  |  |  Branch (66:12): [True: 107, False: 47]
  |  |  |  Branch (66:12): [True: 47, False: 0]
  |  |  ------------------
  |  |   67|      0|         FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \
  |  |  ------------------
  |  |  |  |   52|      0|   do {                                                                          \
  |  |  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |  |  |   54|      0|      abort();                                                                   \
  |  |  |  |   55|      0|   } while(0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   68|      0|      }                                                               \
  |  |   69|    154|   } while(0)
  |  |  ------------------
  |  |  |  Branch (69:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   64|       |
   65|    154|   if(ref_valid_mask == 0xFF && lib_valid_mask == 0x00) {
  ------------------
  |  Branch (65:7): [True: 47, False: 107]
  |  Branch (65:33): [True: 0, False: 47]
  ------------------
   66|      0|      FUZZER_WRITE_AND_CRASH("Ref accepted but library rejected, output " << Botan::hex_encode(ref_output) << "\n");
  ------------------
  |  |   52|      0|   do {                                                                          \
  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |   54|      0|      abort();                                                                   \
  |  |   55|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   67|    154|   } else if(ref_valid_mask == 0x00 && lib_valid_mask == 0xFF) {
  ------------------
  |  Branch (67:14): [True: 107, False: 47]
  |  Branch (67:40): [True: 0, False: 107]
  ------------------
   68|      0|      FUZZER_WRITE_AND_CRASH("Lib accepted but ref rejected, output = " << Botan::hex_encode(lib_output) << "\n");
  ------------------
  |  |   52|      0|   do {                                                                          \
  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |   54|      0|      abort();                                                                   \
  |  |   55|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   69|      0|   }
   70|       |
   71|    154|   if(ref_valid_mask == 0x00) {
  ------------------
  |  Branch (71:7): [True: 107, False: 47]
  ------------------
   72|    107|      FUZZER_ASSERT_TRUE(all_zeros(ref_output));
  ------------------
  |  |   65|    107|   do {                                                               \
  |  |   66|    107|      if(!(e)) {                                                      \
  |  |  ------------------
  |  |  |  Branch (66:10): [True: 0, False: 107]
  |  |  ------------------
  |  |   67|      0|         FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \
  |  |  ------------------
  |  |  |  |   52|      0|   do {                                                                          \
  |  |  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |  |  |   54|      0|      abort();                                                                   \
  |  |  |  |   55|      0|   } while(0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   68|      0|      }                                                               \
  |  |   69|    107|   } while(0)
  |  |  ------------------
  |  |  |  Branch (69:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   73|    107|   }
   74|       |
   75|    154|   if(lib_valid_mask == 0x00) {
  ------------------
  |  Branch (75:7): [True: 107, False: 47]
  ------------------
   76|    107|      FUZZER_ASSERT_TRUE(all_zeros(lib_output));
  ------------------
  |  |   65|    107|   do {                                                               \
  |  |   66|    107|      if(!(e)) {                                                      \
  |  |  ------------------
  |  |  |  Branch (66:10): [True: 0, False: 107]
  |  |  ------------------
  |  |   67|      0|         FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \
  |  |  ------------------
  |  |  |  |   52|      0|   do {                                                                          \
  |  |  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |  |  |   54|      0|      abort();                                                                   \
  |  |  |  |   55|      0|   } while(0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   68|      0|      }                                                               \
  |  |   69|    107|   } while(0)
  |  |  ------------------
  |  |  |  Branch (69:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   77|    107|   }
   78|       |
   79|    154|   if(ref_valid_mask && lib_valid_mask) {
  ------------------
  |  Branch (79:7): [True: 47, False: 107]
  |  Branch (79:25): [True: 47, False: 0]
  ------------------
   80|     47|      if(ref_output != lib_output) {
  ------------------
  |  Branch (80:10): [True: 0, False: 47]
  ------------------
   81|      0|         FUZZER_WRITE_AND_CRASH("Ref and lib both accepted but produced different output:"
  ------------------
  |  |   52|      0|   do {                                                                          \
  |  |   53|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
  |  |   54|      0|      abort();                                                                   \
  |  |   55|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (55:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   82|      0|                                << " ref = " << Botan::hex_encode(ref_output)
   83|      0|                                << " lib = " << Botan::hex_encode(lib_output));
   84|      0|      }
   85|     47|   }
   86|    154|}
oaep.cpp:_ZN12_GLOBAL__N_114ref_oaep_unpadERhPKhmRKNSt3__16vectorIhN5Botan16secure_allocatorIhEEEE:
   17|    154|                                             const Botan::secure_vector<uint8_t>& Phash) {
   18|    154|   const size_t hlen = Phash.size();
   19|       |
   20|    154|   if(len < 2 * hlen + 1) {
  ------------------
  |  Branch (20:7): [True: 6, False: 148]
  ------------------
   21|      6|      return Botan::secure_vector<uint8_t>();
   22|      6|   }
   23|       |
   24|    509|   for(size_t i = hlen; i != 2 * hlen; ++i) {
  ------------------
  |  Branch (24:25): [True: 421, False: 88]
  ------------------
   25|    421|      if(in[i] != Phash[i - hlen]) {
  ------------------
  |  Branch (25:10): [True: 60, False: 361]
  ------------------
   26|     60|         return Botan::secure_vector<uint8_t>();
   27|     60|      }
   28|    421|   }
   29|       |
   30|    714|   for(size_t i = 2 * hlen; i != len; ++i) {
  ------------------
  |  Branch (30:29): [True: 704, False: 10]
  ------------------
   31|    704|      if(in[i] != 0x00 && in[i] != 0x01) {
  ------------------
  |  Branch (31:10): [True: 78, False: 626]
  |  Branch (31:27): [True: 31, False: 47]
  ------------------
   32|     31|         return Botan::secure_vector<uint8_t>();
   33|     31|      }
   34|       |
   35|    673|      if(in[i] == 0x01) {
  ------------------
  |  Branch (35:10): [True: 47, False: 626]
  ------------------
   36|     47|         valid_mask = 0xFF;
   37|     47|         return Botan::secure_vector<uint8_t>(in + i + 1, in + len);
   38|     47|      }
   39|    673|   }
   40|       |
   41|     10|   return Botan::secure_vector<uint8_t>();
   42|     88|}
oaep.cpp:_ZN12_GLOBAL__N_19all_zerosERKNSt3__16vectorIhN5Botan16secure_allocatorIhEEEE:
   44|    214|inline bool all_zeros(const Botan::secure_vector<uint8_t>& v) {
   45|    214|   for(size_t i = 0; i != v.size(); ++i) {
  ------------------
  |  Branch (45:22): [True: 0, False: 214]
  ------------------
   46|      0|      if(v[i] != 0)
  ------------------
  |  Branch (46:10): [True: 0, False: 0]
  ------------------
   47|      0|         return false;
   48|      0|   }
   49|    214|   return true;
   50|    214|}

_ZN5Botan15oaep_find_delimERhPKhmRKNSt3__16vectorIhNS_16secure_allocatorIhEEEE:
   87|    154|                                       const secure_vector<uint8_t>& Phash) {
   88|    154|   const size_t hlen = Phash.size();
   89|       |
   90|       |   // Too short to be valid, reject immediately
   91|    154|   if(input_len < 1 + 2 * hlen) {
  ------------------
  |  Branch (91:7): [True: 6, False: 148]
  ------------------
   92|      6|      return secure_vector<uint8_t>();
   93|      6|   }
   94|       |
   95|    148|   CT::poison(input, input_len);
   96|       |
   97|    148|   size_t delim_idx = 2 * hlen;
   98|    148|   CT::Mask<uint8_t> waiting_for_delim = CT::Mask<uint8_t>::set();
   99|    148|   CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
  100|       |
  101|   184k|   for(size_t i = delim_idx; i < input_len; ++i) {
  ------------------
  |  Branch (101:30): [True: 184k, False: 148]
  ------------------
  102|   184k|      const auto zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
  103|   184k|      const auto one_m = CT::Mask<uint8_t>::is_equal(input[i], 1);
  104|       |
  105|   184k|      const auto add_m = waiting_for_delim & zero_m;
  106|       |
  107|   184k|      bad_input_m |= waiting_for_delim & ~(zero_m | one_m);
  108|       |
  109|   184k|      delim_idx += add_m.if_set_return(1);
  110|       |
  111|   184k|      waiting_for_delim &= zero_m;
  112|   184k|   }
  113|       |
  114|       |   // If we never saw any non-zero byte, then it's not valid input
  115|    148|   bad_input_m |= waiting_for_delim;
  116|    148|   bad_input_m |= CT::Mask<uint8_t>::is_zero(ct_compare_u8(&input[hlen], Phash.data(), hlen));
  117|       |
  118|    148|   delim_idx += 1;
  119|       |
  120|    148|   valid_mask = (~bad_input_m).unpoisoned_value();
  121|    148|   auto output = CT::copy_output(bad_input_m, input, input_len, delim_idx);
  122|       |
  123|    148|   CT::unpoison(input, input_len);
  124|       |
  125|    148|   return output;
  126|    154|}

_ZN5Botan2CT11copy_outputENS0_4MaskIhEEPKhmm:
   14|    148|                                   size_t offset) {
   15|       |   /*
   16|       |   * We do not poison the input here because if we did we would have
   17|       |   * to unpoison it at exit. We assume instead that callers have
   18|       |   * already poisoned the input and will unpoison it at their own
   19|       |   * time.
   20|       |   */
   21|    148|   CT::poison(&offset, sizeof(size_t));
   22|       |
   23|    148|   secure_vector<uint8_t> output(input_length);
   24|       |
   25|    148|   auto bad_input = CT::Mask<size_t>::expand(bad_input_u8);
   26|       |
   27|       |   /*
   28|       |   * If the offset is greater than input_length then the arguments are
   29|       |   * invalid. Ideally we would through an exception but that leaks
   30|       |   * information about the offset. Instead treat it as if the input
   31|       |   * was invalid.
   32|       |   */
   33|    148|   bad_input |= CT::Mask<size_t>::is_gt(offset, input_length);
   34|       |
   35|       |   /*
   36|       |   * If the input is invalid, then set offset == input_length as a result
   37|       |   * at the end we will set output_bytes == 0 causing the final result to
   38|       |   * be an empty vector.
   39|       |   */
   40|    148|   offset = bad_input.select(input_length, offset);
   41|       |
   42|       |   /*
   43|       |   Move the desired output bytes to the front using a slow (O^n)
   44|       |   but constant time loop that does not leak the value of the offset
   45|       |   */
   46|   185k|   for(size_t i = 0; i != input_length; ++i) {
  ------------------
  |  Branch (46:22): [True: 185k, False: 148]
  ------------------
   47|       |      /*
   48|       |      * If bad_input was set then we modified offset to equal the input_length.
   49|       |      * In that case, this_loop will be greater than input_length, and so is_eq
   50|       |      * mask will always be false. As a result none of the input values will be
   51|       |      * written to output.
   52|       |      *
   53|       |      * This is ignoring the possibility of integer overflow of offset + i. But
   54|       |      * for this to happen the input would have to consume nearly the entire
   55|       |      * address space, and we just allocated an output buffer of equal size.
   56|       |      */
   57|   185k|      const size_t this_loop = offset + i;
   58|       |
   59|       |      /*
   60|       |      start index from i rather than 0 since we know j must be >= i + offset
   61|       |      to have any effect, and starting from i does not reveal information
   62|       |      */
   63|   546M|      for(size_t j = i; j != input_length; ++j) {
  ------------------
  |  Branch (63:25): [True: 545M, False: 185k]
  ------------------
   64|   545M|         const uint8_t b = input[j];
   65|   545M|         const auto is_eq = CT::Mask<size_t>::is_equal(j, this_loop);
   66|   545M|         output[i] |= is_eq.if_set_return(b);
   67|   545M|      }
   68|   185k|   }
   69|       |
   70|    148|   const size_t output_bytes = input_length - offset;
   71|       |
   72|    148|   CT::unpoison(output.data(), output.size());
   73|    148|   CT::unpoison(output_bytes);
   74|       |
   75|       |   /*
   76|       |   This is potentially not const time, depending on how std::vector is
   77|       |   implemented. But since we are always reducing length, it should
   78|       |   just amount to setting the member var holding the length.
   79|       |   */
   80|    148|   output.resize(output_bytes);
   81|    148|   return output;
   82|    148|}

_ZN5Botan15allocate_memoryEmm:
   20|    194|BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size) {
   21|    194|   if(elems == 0 || elem_size == 0) {
  ------------------
  |  Branch (21:7): [True: 0, False: 194]
  |  Branch (21:21): [True: 0, False: 194]
  ------------------
   22|      0|      return nullptr;
   23|      0|   }
   24|       |
   25|       |   // Some calloc implementations do not check for overflow (?!?)
   26|       |
   27|    194|   if(!BOTAN_CHECKED_MUL(elems, elem_size).has_value()) {
  ------------------
  |  |   73|    194|#define BOTAN_CHECKED_MUL(x, y) checked_mul(x, y)
  ------------------
  |  Branch (27:7): [True: 0, False: 194]
  ------------------
   28|      0|      throw std::bad_alloc();
   29|      0|   }
   30|       |
   31|       |#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
   32|       |   if(void* p = mlock_allocator::instance().allocate(elems, elem_size)) {
   33|       |      return p;
   34|       |   }
   35|       |#endif
   36|       |
   37|       |#if defined(BOTAN_TARGET_OS_HAS_ALLOC_CONCEAL)
   38|       |   void* ptr = ::calloc_conceal(elems, elem_size);
   39|       |#else
   40|    194|   void* ptr = std::calloc(elems, elem_size);  // NOLINT(*-no-malloc)
   41|    194|#endif
   42|    194|   if(!ptr) {
  ------------------
  |  Branch (42:7): [True: 0, False: 194]
  ------------------
   43|      0|      [[unlikely]] throw std::bad_alloc();
   44|      0|   }
   45|    194|   return ptr;
   46|    194|}
_ZN5Botan17deallocate_memoryEPvmm:
   48|    194|void deallocate_memory(void* p, size_t elems, size_t elem_size) {
   49|    194|   if(p == nullptr) {
  ------------------
  |  Branch (49:7): [True: 0, False: 194]
  ------------------
   50|      0|      [[unlikely]] return;
   51|      0|   }
   52|       |
   53|    194|   secure_scrub_memory(p, elems * elem_size);
   54|       |
   55|       |#if defined(BOTAN_HAS_LOCKING_ALLOCATOR)
   56|       |   if(mlock_allocator::instance().deallocate(p, elems, elem_size)) {
   57|       |      return;
   58|       |   }
   59|       |#endif
   60|       |
   61|    194|   std::free(p);  // NOLINT(*-no-malloc)
   62|    194|}
_ZN5Botan13ct_compare_u8EPKhS1_m:
   70|    148|uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len) {
   71|    148|   volatile uint8_t difference = 0;
   72|       |
   73|    740|   for(size_t i = 0; i != len; ++i) {
  ------------------
  |  Branch (73:22): [True: 592, False: 148]
  ------------------
   74|    592|      difference = difference | (x[i] ^ y[i]);
   75|    592|   }
   76|       |
   77|    148|   return CT::Mask<uint8_t>::is_zero(difference).value();
   78|    148|}

_ZN5Botan19secure_scrub_memoryEPvm:
   78|    194|void secure_scrub_memory(void* ptr, size_t n) {
   79|       |#if defined(BOTAN_TARGET_OS_HAS_RTLSECUREZEROMEMORY)
   80|       |   ::RtlSecureZeroMemory(ptr, n);
   81|       |
   82|       |#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_BZERO)
   83|    194|   ::explicit_bzero(ptr, n);
   84|       |
   85|       |#elif defined(BOTAN_TARGET_OS_HAS_EXPLICIT_MEMSET)
   86|       |   (void)::explicit_memset(ptr, 0, n);
   87|       |
   88|       |#elif defined(BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO) && (BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO == 1)
   89|       |   /*
   90|       |   Call memset through a static volatile pointer, which the compiler
   91|       |   should not elide. This construct should be safe in conforming
   92|       |   compilers, but who knows. I did confirm that on x86-64 GCC 6.1 and
   93|       |   Clang 3.8 both create code that saves the memset address in the
   94|       |   data segment and unconditionally loads and jumps to that address.
   95|       |   */
   96|       |   static void* (*const volatile memset_ptr)(void*, int, size_t) = std::memset;
   97|       |   (memset_ptr)(ptr, 0, n);
   98|       |#else
   99|       |
  100|       |   volatile uint8_t* p = reinterpret_cast<volatile uint8_t*>(ptr);
  101|       |
  102|       |   for(size_t i = 0; i != n; ++i)
  103|       |      p[i] = 0;
  104|       |#endif
  105|    194|}

