_ZN5Botan6chooseITkNSt3__117unsigned_integralEmEET_S2_S2_S2_:
  216|    304|BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b) {
  217|       |   //return (mask & a) | (~mask & b);
  218|    304|   return (b ^ (mask & (a ^ b)));
  219|    304|}
_ZN5Botan17ct_expand_top_bitITkNSt3__117unsigned_integralEmEET_S2_:
   28|   590M|BOTAN_FORCE_INLINE constexpr T ct_expand_top_bit(T a) {
   29|   590M|   const T top = CT::value_barrier<T>(a >> (sizeof(T) * 8 - 1));
   30|   590M|   return static_cast<T>(0) - top;
   31|   590M|}
_ZN5Botan10ct_is_zeroITkNSt3__117unsigned_integralEmEET_S2_:
   37|   590M|BOTAN_FORCE_INLINE constexpr T ct_is_zero(T x) {
   38|   590M|   return ct_expand_top_bit<T>(~x & (x - 1));
   39|   590M|}
_ZN5Botan10ct_is_zeroITkNSt3__117unsigned_integralEhEET_S2_:
   37|   201k|BOTAN_FORCE_INLINE constexpr T ct_is_zero(T x) {
   38|   201k|   return ct_expand_top_bit<T>(~x & (x - 1));
   39|   201k|}
_ZN5Botan17ct_expand_top_bitITkNSt3__117unsigned_integralEhEET_S2_:
   28|   201k|BOTAN_FORCE_INLINE constexpr T ct_expand_top_bit(T a) {
   29|   201k|   const T top = CT::value_barrier<T>(a >> (sizeof(T) * 8 - 1));
   30|   201k|   return static_cast<T>(0) - top;
   31|   201k|}

_ZNK5Botan2CT6OptionImE9has_valueEv:
  664|    169|      constexpr Choice has_value() const { return m_has_value; }
_ZNK5Botan2CT6Choice7as_boolEv:
  329|    169|      constexpr bool as_bool() const { return m_value != 0; }
_ZNK5Botan2CT6OptionImE8value_orEmQsr3stdE17unsigned_integralIT_E:
  701|    169|      {
  702|    169|         auto mask = CT::Mask<T>::from_choice(m_has_value);
  703|    169|         return mask.select(m_value, other);
  704|    169|      }
_ZN5Botan2CT4MaskImE11from_choiceENS0_6ChoiceE:
  402|    304|      static constexpr Mask<T> from_choice(Choice c) {
  403|    304|         if constexpr(sizeof(T) <= sizeof(Choice::underlying_type)) {
  404|       |            // Take advantage of the fact that Choice's mask is always
  405|       |            // either |0| or |1|
  406|    304|            return Mask<T>(static_cast<T>(c.value()));
  407|       |         } else {
  408|       |            return ~Mask<T>::is_zero(c.value());
  409|       |         }
  410|    304|      }
_ZNK5Botan2CT6Choice5valueEv:
  332|    844|      constexpr underlying_type value() const { return value_barrier(m_value); }
_ZN5Botan2CT4MaskImEC2Em:
  637|   590M|      constexpr explicit Mask(T m) : m_mask(m) {}
_ZNK5Botan2CT4MaskImE6selectEmm:
  548|    304|      constexpr T select(T x, T y) const { return choose(value(), x, y); }
_ZNK5Botan2CT4MaskImE5valueEv:
  630|   590M|      constexpr T value() const { return value_barrier<T>(m_mask); }
_ZN5Botan2CT6Choice9from_maskEm:
  303|    135|      constexpr static Choice from_mask(underlying_type v) { return Choice(v); }
_ZN5Botan2CT6Choice2noEv:
  307|     34|      constexpr static Choice no() { return Choice(0); }
_ZNK5Botan2CT6ChoicentEv:
  309|    270|      constexpr Choice operator!() const { return Choice(~value()); }
_ZNK5Botan2CT6ChoiceaaERKS1_:
  311|    135|      constexpr Choice operator&&(const Choice& other) const { return Choice(value() & other.value()); }
_ZN5Botan2CT6ChoiceC2Em:
  341|    709|      constexpr explicit Choice(underlying_type v) : m_value(CT::value_barrier<underlying_type>(v)) {}
_ZN5Botan2CT4MaskImE7is_zeroEm:
  437|   590M|      static constexpr Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(value_barrier<T>(x))); }
_ZNK5Botan2CT4MaskImEcoEv:
  533|    135|      constexpr Mask<T> operator~() const { return Mask<T>(~value()); }
_ZN5Botan2CT6OptionImEC2EvQsr3stdE21default_initializableIT_E:
  661|     34|            : Option(T(), Choice::no()) {}
_ZN5Botan2CT6OptionImEC2EmNS0_6ChoiceE:
  653|    169|      constexpr Option(T v, Choice valid) : m_has_value(valid), m_value(std::move(v)) {}
_ZN5Botan2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS6_EEEDaDpRKS6_:
  222|    135|[[nodiscard]] constexpr auto scoped_poison(const Ts&... xs) {
  223|    135|   auto scope = scoped_cleanup([&] { unpoison_all(xs...); });
  224|    135|   poison_all(xs...);
  225|    135|   return scope;
  226|    135|}
_ZN5Botan2CT10poison_allITpTkNS0_10poisonableEJNSt3__14spanIKhLm18446744073709551615EEEEQgtsZT_Li0EEEvDpRKT_:
  201|    135|constexpr void poison_all(const Ts&... ts) {
  202|    135|   (poison(ts), ...);
  203|    135|}
_ZN5Botan2CT6poisonITkNS_6ranges14spanable_rangeENSt3__14spanIKhLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEnt17custom_poisonableISB_EEEvRKSB_:
  121|    135|constexpr void poison(const R& r) {
  122|    135|   const std::span s{r};
  123|    135|   poison(s.data(), s.size());
  124|    135|}
_ZN5Botan2CT6poisonIhEEvPKT_m:
   56|    135|constexpr inline void poison(const T* p, size_t n) {
   57|       |#if defined(BOTAN_HAS_VALGRIND)
   58|       |   if(!std::is_constant_evaluated()) {
   59|       |      VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
   60|       |   }
   61|       |#endif
   62|       |
   63|    135|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  144|    135|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   64|    135|}
_ZN5Botan2CT4MaskIhE7clearedEv:
  387|    270|      static constexpr Mask<T> cleared() { return Mask<T>(0); }
_ZN5Botan2CT4MaskIhEC2Eh:
  637|   202k|      constexpr explicit Mask(T m) : m_mask(m) {}
_ZN5Botan2CT4MaskIhE8is_equalEhh:
  442|    270|      static constexpr Mask<T> is_equal(T x, T y) {
  443|    270|         const T diff = value_barrier(x) ^ value_barrier(y);
  444|    270|         return Mask<T>::is_zero(diff);
  445|    270|      }
_ZNK5Botan2CT4MaskIhEcoEv:
  533|    405|      constexpr Mask<T> operator~() const { return Mask<T>(~value()); }
_ZNK5Botan2CT4MaskIhE5valueEv:
  630|   403k|      constexpr T value() const { return value_barrier<T>(m_mask); }
_ZN5Botan2CT4MaskIhE7is_zeroEh:
  437|   201k|      static constexpr Mask<T> is_zero(T x) { return Mask<T>(ct_is_zero<T>(value_barrier<T>(x))); }
_ZNK5Botan2CT4MaskIhE17if_not_set_returnEh:
  543|   201k|      constexpr T if_not_set_return(T x) const { return ~value() & x; }
_ZN5Botan2CT4MaskImE5is_ltEmm:
  450|    270|      static constexpr Mask<T> is_lt(T x, T y) {
  451|    270|         T u = x ^ ((x ^ y) | ((x - y) ^ x));
  452|    270|         return Mask<T>::expand_top_bit(u);
  453|    270|      }
_ZN5Botan2CT4MaskImE14expand_top_bitEm:
  415|    270|      static constexpr Mask<T> expand_top_bit(T v) { return Mask<T>(ct_expand_top_bit<T>(v)); }
_ZN5Botan2CT4MaskIhEC2ImEENS1_IT_EE:
  375|    135|      constexpr explicit Mask(Mask<U> o) : m_mask(static_cast<T>(o.value())) {
  376|    135|         static_assert(sizeof(U) > sizeof(T), "sizes ok");
  377|    135|      }
_ZNK5Botan2CT4MaskIhE9as_choiceEv:
  619|    135|      constexpr CT::Choice as_choice() const {
  620|       |         if constexpr(sizeof(T) >= sizeof(Choice::underlying_type)) {
  621|       |            return CT::Choice::from_mask(static_cast<Choice::underlying_type>(unpoisoned_value()));
  622|    135|         } else {
  623|    135|            return CT::Choice::from_int(unpoisoned_value());
  624|    135|         }
  625|    135|      }
_ZN5Botan2CT6Choice8from_intIhQaasr3stdE17unsigned_integralIT_Entsr3stdE7same_asIbS3_EEES1_S3_:
  268|    135|      constexpr static Choice from_int(T v) {
  269|    135|         if constexpr(sizeof(T) <= sizeof(underlying_type)) {
  270|    135|            return !Choice(ct_is_zero<underlying_type>(v));
  271|       |         } else {
  272|       |            // Mask of T that is either |0| or |1|
  273|       |            const T v_is_0 = ct_is_zero<T>(value_barrier<T>(v));
  274|       |
  275|       |            // We want the mask to be set if v != 0 so we must check that
  276|       |            // v_is_0 is itself zero.
  277|       |            //
  278|       |            // Also sizeof(T) may not equal sizeof(underlying_type) so we must
  279|       |            // use ct_is_zero<underlying_type>. It's ok to either truncate or
  280|       |            // zero extend v_is_0 to 32 bits since we know it is |0| or |1|
  281|       |            // so even just the low bit is sufficient.
  282|       |            return Choice(ct_is_zero<underlying_type>(static_cast<underlying_type>(v_is_0)));
  283|       |         }
  284|    135|      }
_ZNK5Botan2CT4MaskIhE16unpoisoned_valueEv:
  598|    135|      constexpr T unpoisoned_value() const {
  599|    135|         T r = value();
  600|    135|         CT::unpoison(r);
  601|    135|         return r;
  602|    135|      }
_ZN5Botan2CT8unpoisonITkNSt3__18integralEhEEvRKT_:
  112|    135|constexpr void unpoison(const T& p) {
  113|    135|   unpoison(&p, 1);
  114|    135|}
_ZN5Botan2CT8unpoisonIhEEvPKT_m:
   67|    405|constexpr inline void unpoison(const T* p, size_t n) {
   68|       |#if defined(BOTAN_HAS_VALGRIND)
   69|       |   if(!std::is_constant_evaluated()) {
   70|       |      VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
   71|       |   }
   72|       |#endif
   73|       |
   74|    405|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  144|    405|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   75|    405|}
_ZZN5Botan2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS6_EEEDaDpRKS6_ENKUlvE_clEv:
  223|    135|   auto scope = scoped_cleanup([&] { unpoison_all(xs...); });
_ZN5Botan2CT12unpoison_allITpTkNS0_12unpoisonableEJNSt3__14spanIKhLm18446744073709551615EEEEQgtsZT_Li0EEEvDpRKT_:
  207|    135|constexpr void unpoison_all(const Ts&... ts) {
  208|    135|   (unpoison(ts), ...);
  209|    135|}
_ZN5Botan2CT8unpoisonITkNS_6ranges14spanable_rangeENSt3__14spanIKhLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISE_EESF_E4type10value_typeEEnt19custom_unpoisonableISB_EEEvRKSB_:
  128|    135|constexpr void unpoison(const R& r) {
  129|    135|   const std::span s{r};
  130|    135|   unpoison(s.data(), s.size());
  131|    135|}
_ZN5Botan2CT4MaskIhEoRES2_:
  510|   201k|      Mask<T>& operator|=(Mask<T> o) {
  511|   201k|         m_mask |= o.value();
  512|   201k|         return (*this);
  513|   201k|      }
_ZN5Botan2CT6poisonITkNSt3__18integralEmEEvRKT_:
  107|    135|constexpr void poison(const T& p) {
  108|    135|   poison(&p, 1);
  109|    135|}
_ZN5Botan2CT6poisonImEEvPKT_m:
   56|    135|constexpr inline void poison(const T* p, size_t n) {
   57|       |#if defined(BOTAN_HAS_VALGRIND)
   58|       |   if(!std::is_constant_evaluated()) {
   59|       |      VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
   60|       |   }
   61|       |#endif
   62|       |
   63|    135|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  144|    135|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   64|    135|}
_ZN5Botan2CT4MaskImE6is_lteEmm:
  463|    135|      static constexpr Mask<T> is_lte(T x, T y) { return ~Mask<T>::is_gt(x, y); }
_ZN5Botan2CT4MaskImE5is_gtEmm:
  458|    135|      static constexpr Mask<T> is_gt(T x, T y) { return Mask<T>::is_lt(y, x); }
_ZNK5Botan2CT4MaskImE9as_choiceEv:
  619|    135|      constexpr CT::Choice as_choice() const {
  620|    135|         if constexpr(sizeof(T) >= sizeof(Choice::underlying_type)) {
  621|    135|            return CT::Choice::from_mask(static_cast<Choice::underlying_type>(unpoisoned_value()));
  622|       |         } else {
  623|       |            return CT::Choice::from_int(unpoisoned_value());
  624|       |         }
  625|    135|      }
_ZNK5Botan2CT4MaskImE16unpoisoned_valueEv:
  598|    135|      constexpr T unpoisoned_value() const {
  599|    135|         T r = value();
  600|    135|         CT::unpoison(r);
  601|    135|         return r;
  602|    135|      }
_ZN5Botan2CT8unpoisonITkNSt3__18integralEmEEvRKT_:
  112|    270|constexpr void unpoison(const T& p) {
  113|    270|   unpoison(&p, 1);
  114|    270|}
_ZN5Botan2CT8unpoisonImEEvPKT_m:
   67|    270|constexpr inline void unpoison(const T* p, size_t n) {
   68|       |#if defined(BOTAN_HAS_VALGRIND)
   69|       |   if(!std::is_constant_evaluated()) {
   70|       |      VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
   71|       |   }
   72|       |#endif
   73|       |
   74|    270|   BOTAN_UNUSED(p, n);
  ------------------
  |  |  144|    270|#define BOTAN_UNUSED Botan::ignore_params
  ------------------
   75|    270|}
_ZN5Botan2CT4MaskImE8is_equalEmm:
  442|   590M|      static constexpr Mask<T> is_equal(T x, T y) {
  443|   590M|         const T diff = value_barrier(x) ^ value_barrier(y);
  444|   590M|         return Mask<T>::is_zero(diff);
  445|   590M|      }
_ZNK5Botan2CT4MaskImE13if_set_returnEm:
  538|   590M|      constexpr T if_set_return(T x) const { return value() & x; }
_ZN5Botan2CT12unpoison_allITpTkNS0_12unpoisonableEJNSt3__14spanIhLm18446744073709551615EEEmEQgtsZT_Li0EEEvDpRKT_:
  207|    135|constexpr void unpoison_all(const Ts&... ts) {
  208|    135|   (unpoison(ts), ...);
  209|    135|}
_ZN5Botan2CT8unpoisonITkNS_6ranges14spanable_rangeENSt3__14spanIhLm18446744073709551615EEEQaasr3stdE23is_trivially_copyable_vINS3_11conditionalIXsr21__is_primary_templateINS3_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS3_6ranges5__cpo5beginEEclsr3stdE7declvalIRT_EEEEEEEEE5valueENS3_26indirectly_readable_traitsISD_EESE_E4type10value_typeEEnt19custom_unpoisonableISA_EEEvRKSA_:
  128|    135|constexpr void unpoison(const R& r) {
  129|    135|   const std::span s{r};
  130|    135|   unpoison(s.data(), s.size());
  131|    135|}

_ZN5Botan14scoped_cleanupIZNS_2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS7_EEEDaDpRKS7_EUlvE_EC2ESB_:
   26|    135|      explicit scoped_cleanup(FunT cleanup) : m_cleanup(std::move(cleanup)) {}
_ZN5Botan14scoped_cleanupIZNS_2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS7_EEEDaDpRKS7_EUlvE_EC2EOSC_:
   31|    135|      scoped_cleanup(scoped_cleanup&& other) noexcept : m_cleanup(std::move(other.m_cleanup)) { other.disengage(); }
_ZN5Botan14scoped_cleanupIZNS_2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS7_EEEDaDpRKS7_EUlvE_E9disengageEv:
   50|    135|      void disengage() noexcept { m_cleanup.reset(); }
_ZN5Botan14scoped_cleanupIZNS_2CT13scoped_poisonIJNSt3__14spanIKhLm18446744073709551615EEEEQaaaagtsZT_Li0Efraa10poisonableIT_Efraa12unpoisonableIS7_EEEDaDpRKS7_EUlvE_ED2Ev:
   41|    270|      ~scoped_cleanup() {
   42|    270|         if(m_cleanup.has_value()) {
  ------------------
  |  Branch (42:13): [True: 135, False: 135]
  ------------------
   43|    135|            (*m_cleanup)();  // NOLINT(bugprone-exception-escape) clang-tidy bug
   44|    135|         }
   45|    270|      }

_ZN5Botan2CT13value_barrierITkNSt3__117unsigned_integralEmQntsr3stdE7same_asIbT_EEES3_S3_:
   43|  2.95G|constexpr inline T value_barrier(T x) {
   44|  2.95G|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (44:7): [Folded, False: 2.95G]
  ------------------
   45|      0|      return x;
   46|  2.95G|   } else {
   47|  2.95G|#if defined(BOTAN_CT_VALUE_BARRIER_USE_ASM)
   48|       |      /*
   49|       |      * We may want a "stronger" statement such as
   50|       |      *     asm volatile("" : "+r,m"(x) : : "memory);
   51|       |      * (see https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html)
   52|       |      * however the current approach seems sufficient with current compilers,
   53|       |      * and is minimally damaging with regards to degrading code generation.
   54|       |      */
   55|  2.95G|      asm("" : "+r"(x) : /* no input */);  // NOLINT(*-no-assembler)
   56|  2.95G|      return x;
   57|       |#elif defined(BOTAN_CT_VALUE_BARRIER_USE_VOLATILE)
   58|       |      volatile T vx = x;
   59|       |      return vx;
   60|       |#else
   61|       |      return x;
   62|       |#endif
   63|  2.95G|   }
   64|  2.95G|}
_ZN5Botan2CT13value_barrierITkNSt3__117unsigned_integralEhQntsr3stdE7same_asIbT_EEES3_S3_:
   43|   806k|constexpr inline T value_barrier(T x) {
   44|   806k|   if(std::is_constant_evaluated()) {
  ------------------
  |  Branch (44:7): [Folded, False: 806k]
  ------------------
   45|      0|      return x;
   46|   806k|   } else {
   47|   806k|#if defined(BOTAN_CT_VALUE_BARRIER_USE_ASM)
   48|       |      /*
   49|       |      * We may want a "stronger" statement such as
   50|       |      *     asm volatile("" : "+r,m"(x) : : "memory);
   51|       |      * (see https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html)
   52|       |      * however the current approach seems sufficient with current compilers,
   53|       |      * and is minimally damaging with regards to degrading code generation.
   54|       |      */
   55|   806k|      asm("" : "+r"(x) : /* no input */);  // NOLINT(*-no-assembler)
   56|   806k|      return x;
   57|       |#elif defined(BOTAN_CT_VALUE_BARRIER_USE_VOLATILE)
   58|       |      volatile T vx = x;
   59|       |      return vx;
   60|       |#else
   61|       |      return x;
   62|       |#endif
   63|   806k|   }
   64|   806k|}

_ZN5Botan13ignore_paramsIJPKhmEEEvDpRKT_:
  142|    540|constexpr void ignore_params([[maybe_unused]] const T&... args) {}
_ZN5Botan13ignore_paramsIJPKmmEEEvDpRKT_:
  142|    405|constexpr void ignore_params([[maybe_unused]] const T&... args) {}

_ZN5Botan11clear_bytesEPvm:
  101|    135|inline constexpr void clear_bytes(void* ptr, size_t bytes) {
  102|    135|   if(bytes > 0) {
  ------------------
  |  Branch (102:7): [True: 135, False: 0]
  ------------------
  103|    135|      std::memset(ptr, 0, bytes);
  104|    135|   }
  105|    135|}
_ZN5Botan9clear_memITkNS_6ranges23contiguous_output_rangeERNSt3__14spanIhLm18446744073709551615EEEEEvOT_Qsr3stdE23is_trivially_copyable_vINS2_11conditionalIXsr21__is_primary_templateINS2_15iterator_traitsIu14__remove_cvrefIDTclL_ZNS2_6ranges5__cpo5beginEEclsr3stdE7declvalIRS6_EEEEEEEEE5valueENS2_26indirectly_readable_traitsISE_EESF_E4type10value_typeEE:
  132|    135|{
  133|    135|   clear_bytes(std::ranges::data(mem), ranges::size_bytes(mem));
  134|    135|}

_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeENSt3__14spanIhLm18446744073709551615EEEEEmRKT_:
   59|    135|inline constexpr size_t size_bytes(const spanable_range auto& r) {
   60|    135|   return std::span{r}.size_bytes();
   61|    135|}

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|    179|extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
   40|    179|   if(len <= max_fuzzer_input_size) {
  ------------------
  |  Branch (40:7): [True: 169, False: 10]
  ------------------
   41|    169|      try {
   42|    169|         fuzz(std::span<const uint8_t>(in, len));
   43|    169|      } 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|    169|   }
   51|    179|   return 0;
   52|    179|}

_Z4fuzzNSt3__14spanIKhLm18446744073709551615EEE:
   37|    169|void fuzz(std::span<const uint8_t> in) {
   38|    169|   static Botan::EME_PKCS1v15 pkcs1;
   39|       |
   40|    169|   std::vector<uint8_t> lib_result;
   41|    169|   std::vector<uint8_t> ref_result;
   42|    169|   bool lib_rejected = false;
   43|    169|   bool ref_rejected = false;
   44|       |
   45|    169|   try {
   46|    169|      lib_result.resize(in.size());
   47|    169|      auto written = (static_cast<Botan::EncryptionPaddingScheme*>(&pkcs1))->unpad(lib_result, in);
   48|    169|      lib_rejected = !written.has_value().as_bool();
   49|       |
   50|    169|      lib_result.resize(written.value_or(0));
   51|    169|   } catch(const Botan::Decoding_Error&) {
   52|      0|      lib_rejected = true;
   53|      0|   }
   54|       |
   55|    169|   try {
   56|    169|      ref_result = simple_pkcs1_unpad(in.data(), in.size());
   57|    169|   } catch(const Botan::Decoding_Error& e) {
   58|     84|      ref_rejected = true;
   59|     84|   }
   60|       |
   61|    169|   if(lib_rejected == true && ref_rejected == false) {
  ------------------
  |  Branch (61:7): [True: 84, False: 85]
  |  Branch (61:31): [True: 0, False: 84]
  ------------------
   62|      0|      FUZZER_WRITE_AND_CRASH("Library rejected input accepted by ref " << Botan::hex_encode(ref_result));
  ------------------
  |  |   70|      0|   do {                                                                                                       \
  |  |   71|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; /* NOLINT(*-macro-paren*) */ \
  |  |   72|      0|      abort();                                                                                                \
  |  |   73|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (73:12): [Folded, False: 0]
  |  |  ------------------
  ------------------
   63|    169|   } else if(ref_rejected == true && lib_rejected == false) {
  ------------------
  |  Branch (63:14): [True: 84, False: 85]
  |  Branch (63:38): [True: 0, False: 84]
  ------------------
   64|      0|      FUZZER_WRITE_AND_CRASH("Library accepted input rejected by ref " << Botan::hex_encode(lib_result));
  ------------------
  |  |   70|      0|   do {                                                                                                       \
  |  |   71|      0|      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; /* NOLINT(*-macro-paren*) */ \
  |  |   72|      0|      abort();                                                                                                \
  |  |   73|      0|   } while(0)
  |  |  ------------------
  |  |  |  Branch (73:12): [Folded, False: 0]
  |  |  ------------------
  ------------------
   65|      0|   }
   66|       |   // otherwise the two implementations agree
   67|    169|}
pkcs1.cpp:_ZN12_GLOBAL__N_118simple_pkcs1_unpadEPKhm:
   14|    169|std::vector<uint8_t> simple_pkcs1_unpad(const uint8_t in[], size_t len) {
   15|    169|   if(len < 10) {
  ------------------
  |  Branch (15:7): [True: 10, False: 159]
  ------------------
   16|     10|      throw Botan::Decoding_Error("bad len");
   17|     10|   }
   18|       |
   19|    159|   if(in[0] != 0 || in[1] != 2) {
  ------------------
  |  Branch (19:7): [True: 34, False: 125]
  |  Branch (19:21): [True: 21, False: 104]
  ------------------
   20|     55|      throw Botan::Decoding_Error("bad header field");
   21|     55|   }
   22|       |
   23|  79.5k|   for(size_t i = 2; i < len; ++i) {
  ------------------
  |  Branch (23:22): [True: 79.4k, False: 6]
  ------------------
   24|  79.4k|      if(in[i] == 0) {
  ------------------
  |  Branch (24:10): [True: 98, False: 79.3k]
  ------------------
   25|     98|         if(i < 10) {  // at least 8 padding bytes required
  ------------------
  |  Branch (25:13): [True: 13, False: 85]
  ------------------
   26|     13|            throw Botan::Decoding_Error("insufficient padding bytes");
   27|     13|         }
   28|     85|         return std::vector<uint8_t>(in + i + 1, in + len);
   29|     98|      }
   30|  79.4k|   }
   31|       |
   32|      6|   throw Botan::Decoding_Error("delim not found");
   33|    104|}

_ZNK5Botan12EME_PKCS1v155unpadENSt3__14spanIhLm18446744073709551615EEENS2_IKhLm18446744073709551615EEE:
   52|    169|CT::Option<size_t> EME_PKCS1v15::unpad(std::span<uint8_t> output, std::span<const uint8_t> input) const {
   53|    169|   BOTAN_ASSERT_NOMSG(output.size() >= input.size());
  ------------------
  |  |   77|    169|   do {                                                                     \
  |  |   78|    169|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */                         \
  |  |   79|    169|      if(!(expr)) {                                                         \
  |  |  ------------------
  |  |  |  Branch (79:10): [True: 0, False: 169]
  |  |  ------------------
  |  |   80|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */                \
  |  |   81|      0|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   82|      0|      }                                                                     \
  |  |   83|    169|   } while(0)
  |  |  ------------------
  |  |  |  Branch (83:12): [Folded, False: 169]
  |  |  ------------------
  ------------------
   54|       |
   55|       |   /*
   56|       |   * RSA decryption pads the ciphertext up to the modulus size, so this only
   57|       |   * occurs with very (!) small keys, or when fuzzing.
   58|       |   *
   59|       |   * 11 bytes == 00,02 + 8 bytes mandatory padding + 00
   60|       |   */
   61|    169|   if(input.size() < 11) {
  ------------------
  |  Branch (61:7): [True: 34, False: 135]
  ------------------
   62|     34|      return {};
   63|     34|   }
   64|       |
   65|    135|   auto scope = CT::scoped_poison(input);
   66|       |
   67|    135|   CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
   68|    135|   CT::Mask<uint8_t> seen_zero_m = CT::Mask<uint8_t>::cleared();
   69|    135|   size_t delim_idx = 2;  // initial 0002
   70|       |
   71|    135|   bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[0], 0);
   72|    135|   bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[1], 2);
   73|       |
   74|   201k|   for(size_t i = 2; i < input.size(); ++i) {
  ------------------
  |  Branch (74:22): [True: 201k, False: 135]
  ------------------
   75|   201k|      const auto is_zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
   76|   201k|      delim_idx += seen_zero_m.if_not_set_return(1);
   77|   201k|      seen_zero_m |= is_zero_m;
   78|   201k|   }
   79|       |
   80|       |   // no zero delim -> bad padding
   81|    135|   bad_input_m |= ~seen_zero_m;
   82|       |   /*
   83|       |   delim indicates < 8 bytes padding -> bad padding
   84|       |
   85|       |   We require 11 here because we are counting also the 00 delim byte
   86|       |   */
   87|    135|   bad_input_m |= CT::Mask<uint8_t>(CT::Mask<size_t>::is_lt(delim_idx, 11));
   88|       |
   89|    135|   const CT::Choice accept = !(bad_input_m.as_choice());
   90|       |
   91|    135|   return CT::copy_output(accept, output, input, delim_idx);
   92|    169|}

_ZN5Botan23EncryptionPaddingSchemeD2Ev:
   68|      1|EncryptionPaddingScheme::~EncryptionPaddingScheme() = default;

_ZN5Botan2CT11copy_outputENS0_6ChoiceENSt3__14spanIhLm18446744073709551615EEENS3_IKhLm18446744073709551615EEEm:
   16|    135|                                   size_t offset) {
   17|       |   // This leaks information about the input length, but this happens
   18|       |   // unavoidably since we are unable to ready any bytes besides those
   19|       |   // in input[0..n]
   20|    135|   BOTAN_ARG_CHECK(output.size() >= input.size(), "Invalid span lengths");
  ------------------
  |  |   35|    135|   do {                                                          \
  |  |   36|    135|      /* NOLINTNEXTLINE(*-simplify-boolean-expr) */              \
  |  |   37|    135|      if(!(expr)) {                                              \
  |  |  ------------------
  |  |  |  Branch (37:10): [True: 0, False: 135]
  |  |  ------------------
  |  |   38|      0|         /* NOLINTNEXTLINE(bugprone-lambda-function-name) */     \
  |  |   39|      0|         Botan::throw_invalid_argument(msg, __func__, __FILE__); \
  |  |   40|      0|      }                                                          \
  |  |   41|    135|   } while(0)
  |  |  ------------------
  |  |  |  Branch (41:12): [Folded, False: 135]
  |  |  ------------------
  ------------------
   21|       |
   22|       |   /*
   23|       |   * We do not poison the input here because if we did we would have
   24|       |   * to unpoison it at exit. We assume instead that callers have
   25|       |   * already poisoned the input and will unpoison it at their own
   26|       |   * time.
   27|       |   */
   28|    135|   CT::poison(offset);
   29|       |
   30|       |   /**
   31|       |   * Zeroize the entire output buffer to get started
   32|       |   */
   33|    135|   clear_mem(output);
   34|       |
   35|       |   /*
   36|       |   * If the offset is greater than input length, then the arguments are
   37|       |   * invalid. Ideally we would throw an exception, but that leaks
   38|       |   * information about the offset. Instead treat it as if the input
   39|       |   * was invalid.
   40|       |   */
   41|    135|   accept = accept && CT::Mask<size_t>::is_lte(offset, input.size()).as_choice();
   42|       |
   43|       |   /*
   44|       |   * If the input is invalid, then set offset == input_length
   45|       |   */
   46|    135|   offset = CT::Mask<size_t>::from_choice(accept).select(offset, input.size());
   47|       |
   48|       |   /*
   49|       |   * Move the desired output bytes to the front using a slow (O^n)
   50|       |   * but constant time loop that does not leak the value of the offset
   51|       |   */
   52|   201k|   for(size_t i = 0; i != input.size(); ++i) {
  ------------------
  |  Branch (52:22): [True: 201k, False: 135]
  ------------------
   53|       |      /*
   54|       |      * If bad_input was set then we modified offset to equal the input_length.
   55|       |      * In that case, this_loop will be greater than input_length, and so is_eq
   56|       |      * mask will always be false. As a result none of the input values will be
   57|       |      * written to output.
   58|       |      *
   59|       |      * This is ignoring the possibility of integer overflow of offset + i. But
   60|       |      * for this to happen the input would have to consume nearly the entire
   61|       |      * address space.
   62|       |      */
   63|   201k|      const size_t this_loop = offset + i;
   64|       |
   65|       |      /*
   66|       |      start index from i rather than 0 since we know j must be >= i + offset
   67|       |      to have any effect, and starting from i does not reveal information
   68|       |      */
   69|   590M|      for(size_t j = i; j != input.size(); ++j) {
  ------------------
  |  Branch (69:25): [True: 590M, False: 201k]
  ------------------
   70|   590M|         const uint8_t b = input[j];
   71|   590M|         const auto is_eq = CT::Mask<size_t>::is_equal(j, this_loop);
   72|   590M|         output[i] |= is_eq.if_set_return(b);
   73|   590M|      }
   74|   201k|   }
   75|       |
   76|       |   // This will always be zero if the input was invalid
   77|    135|   const size_t output_bytes = input.size() - offset;
   78|       |
   79|    135|   CT::unpoison_all(output, output_bytes);
   80|       |
   81|    135|   return CT::Option<size_t>(output_bytes, accept);
   82|    135|}

_ZN5Botan9ExceptionC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
   71|     84|Exception::Exception(std::string_view msg) : m_msg(msg) {}
_ZN5Botan14Decoding_ErrorC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEE:
  125|     84|Decoding_Error::Decoding_Error(std::string_view name) : Exception(name) {}

