_ZN5Botan13is_power_of_2ImEEbT_:
   47|   137k|{
   48|   137k|   return (arg != 0) && (arg != 1) && ((arg & static_cast<T>(arg - 1)) == 0);
  ------------------
  |  Branch (48:11): [True: 137k, False: 0]
  |  Branch (48:25): [True: 137k, False: 0]
  |  Branch (48:39): [True: 76.5k, False: 60.6k]
  ------------------
   49|   137k|}

_ZN5Botan11clear_bytesEPvm:
   92|  4.62k|inline constexpr void clear_bytes(void* ptr, size_t bytes) {
   93|  4.62k|   if(bytes > 0) {
  ------------------
  |  Branch (93:7): [True: 4.62k, False: 0]
  ------------------
   94|  4.62k|      std::memset(ptr, 0, bytes);
   95|  4.62k|   }
   96|  4.62k|}

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|  1.16k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
   35|  1.16k|   if(len <= max_fuzzer_input_size) {
  ------------------
  |  Branch (35:7): [True: 1.15k, False: 10]
  ------------------
   36|  1.15k|      fuzz(in, len);
   37|  1.15k|   }
   38|  1.16k|   return 0;
   39|  1.16k|}

_Z4fuzzPKhm:
   71|  1.15k|void fuzz(const uint8_t in[], size_t in_len) {
   72|  1.15k|   const size_t page_count = 4;
   73|  1.15k|   const size_t page_size = 4096;
   74|       |
   75|       |   // static to avoid repeated allocations
   76|  1.15k|   static std::vector<RawPage> raw_mem = allocate_raw_pages(page_count, page_size);
   77|       |
   78|  1.15k|   std::vector<void*> mem_pages;
   79|  1.15k|   mem_pages.reserve(raw_mem.size());
   80|  5.78k|   for(size_t i = 0; i != raw_mem.size(); ++i)
  ------------------
  |  Branch (80:22): [True: 4.62k, False: 1.15k]
  ------------------
   81|  4.62k|      mem_pages.push_back(raw_mem[i].ptr());
   82|       |
   83|  1.15k|   Botan::Memory_Pool pool(mem_pages, page_size);
   84|  1.15k|   std::map<uint8_t*, size_t> ptrs;
   85|       |
   86|   265k|   while(in_len > 0) {
  ------------------
  |  Branch (86:10): [True: 264k, False: 1.15k]
  ------------------
   87|   264k|      const uint8_t op = in[0] % 2;
   88|   264k|      size_t idx = (in[0] >> 1);
   89|   264k|      in += 1;
   90|   264k|      in_len -= 1;
   91|       |
   92|   264k|      if(in_len > 0 && idx < 4) {
  ------------------
  |  Branch (92:10): [True: 263k, False: 1.10k]
  |  Branch (92:24): [True: 3.71k, False: 259k]
  ------------------
   93|  3.71k|         idx = idx * 256 + in[0];
   94|  3.71k|         in += 1;
   95|  3.71k|         in_len -= 1;
   96|  3.71k|      }
   97|       |
   98|   264k|      if(op == 0) {
  ------------------
  |  Branch (98:10): [True: 150k, False: 113k]
  ------------------
   99|   150k|         const size_t plen = idx + 1;  // ensure non-zero
  100|   150k|         uint8_t* p = static_cast<uint8_t*>(pool.allocate(plen));
  101|       |
  102|   150k|         if(p) {
  ------------------
  |  Branch (102:13): [True: 137k, False: 13.2k]
  ------------------
  103|   137k|            const size_t expected_alignment = compute_expected_alignment(plen);
  104|   137k|            const size_t alignment = reinterpret_cast<uintptr_t>(p) % expected_alignment;
  105|   137k|            if(alignment != 0) {
  ------------------
  |  Branch (105:16): [True: 0, False: 137k]
  ------------------
  106|      0|               FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer "
  ------------------
  |  |   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]
  |  |  ------------------
  ------------------
  107|      0|                                      << static_cast<void*>(p) << " for len " << plen << " expected "
  108|      0|                                      << expected_alignment << " got " << alignment);
  109|      0|            }
  110|       |
  111|       |            //printf("alloc %d -> %p\n", plen, p);
  112|       |
  113|  7.44M|            for(size_t i = 0; i != plen; ++i) {
  ------------------
  |  Branch (113:31): [True: 7.30M, False: 137k]
  ------------------
  114|  7.30M|               if(p[i] != 0) {
  ------------------
  |  Branch (114:19): [True: 0, False: 7.30M]
  ------------------
  115|      0|                  FUZZER_WRITE_AND_CRASH("Pool gave out non-zeroed memory");
  ------------------
  |  |   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]
  |  |  ------------------
  ------------------
  116|      0|               }
  117|  7.30M|            }
  118|       |
  119|       |            // verify it becomes zeroed later
  120|   137k|            std::memset(p, static_cast<int>(idx), plen);
  121|       |
  122|   137k|            auto insert = ptrs.insert(std::make_pair(p, plen));
  123|   137k|            if(insert.second == false) {
  ------------------
  |  Branch (123:16): [True: 0, False: 137k]
  ------------------
  124|      0|               FUZZER_WRITE_AND_CRASH("Pointer " << static_cast<void*>(p) << " already existed\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]
  |  |  ------------------
  ------------------
  125|      0|            }
  126|       |
  127|   137k|            auto itr = insert.first;
  128|       |
  129|       |            // Verify this pointer doesn't overlap with the one before it
  130|   137k|            if(itr != ptrs.begin()) {
  ------------------
  |  Branch (130:16): [True: 78.1k, False: 59.1k]
  ------------------
  131|  78.1k|               auto before = std::prev(itr);
  132|  78.1k|               auto ptr_before = *before;
  133|       |
  134|  78.1k|               if(ptr_before.first + ptr_before.second > p) {
  ------------------
  |  Branch (134:19): [True: 0, False: 78.1k]
  ------------------
  135|      0|                  FUZZER_WRITE_AND_CRASH("Previous " << static_cast<void*>(ptr_before.first) << "/" << ptr_before.second
  ------------------
  |  |   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]
  |  |  ------------------
  ------------------
  136|      0|                                                     << " overlaps with new " << static_cast<void*>(p));
  137|      0|               }
  138|  78.1k|            }
  139|       |
  140|   137k|            auto after = std::next(itr);
  141|       |
  142|   137k|            if(after != ptrs.end()) {
  ------------------
  |  Branch (142:16): [True: 53.2k, False: 84.0k]
  ------------------
  143|  53.2k|               if(p + plen > after->first) {
  ------------------
  |  Branch (143:19): [True: 0, False: 53.2k]
  ------------------
  144|      0|                  FUZZER_WRITE_AND_CRASH("New " << static_cast<void*>(p) << "/" << plen << " overlaps following "
  ------------------
  |  |   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]
  |  |  ------------------
  ------------------
  145|      0|                                                << static_cast<void*>(after->first));
  146|      0|               }
  147|  53.2k|            }
  148|   137k|         }
  149|   150k|      } else if(op == 1) {
  ------------------
  |  Branch (149:17): [True: 113k, False: 0]
  ------------------
  150|   113k|         if(ptrs.empty())
  ------------------
  |  Branch (150:13): [True: 4.85k, False: 109k]
  ------------------
  151|  4.85k|            continue;
  152|       |
  153|   109k|         size_t which_ptr = idx % ptrs.size();
  154|       |
  155|   109k|         auto itr = ptrs.begin();
  156|       |
  157|   996k|         while(which_ptr-- > 0) {
  ------------------
  |  Branch (157:16): [True: 887k, False: 109k]
  ------------------
  158|   887k|            ++itr;
  159|   887k|         }
  160|       |
  161|       |         //printf("free %p %d\n", itr->first, itr->second);
  162|   109k|         FUZZER_ASSERT_TRUE(pool.deallocate(itr->first, itr->second));
  ------------------
  |  |   65|   109k|   do {                                                               \
  |  |   66|   109k|      if(!(e)) {                                                      \
  |  |  ------------------
  |  |  |  Branch (66:10): [True: 0, False: 109k]
  |  |  ------------------
  |  |   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|   109k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (69:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  163|   109k|         ptrs.erase(itr);
  164|   109k|      }
  165|   264k|   }
  166|  1.15k|}
mem_pool.cpp:_ZN12_GLOBAL__N_118allocate_raw_pagesEmm:
   51|      1|std::vector<RawPage> allocate_raw_pages(size_t count, size_t page_size) {
   52|      1|   std::vector<RawPage> pages;
   53|      1|   pages.reserve(count);
   54|       |
   55|      5|   for(size_t i = 0; i != count; ++i) {
  ------------------
  |  Branch (55:22): [True: 4, False: 1]
  ------------------
   56|      4|      void* ptr = nullptr;
   57|       |
   58|      4|      int rc = ::posix_memalign(&ptr, page_size, page_size);
   59|      4|      FUZZER_ASSERT_EQUAL(rc, 0);
  ------------------
  |  |   58|      4|   do {                                                                                  \
  |  |   59|      4|      if(x != y) {                                                                       \
  |  |  ------------------
  |  |  |  Branch (59:10): [True: 0, False: 4]
  |  |  ------------------
  |  |   60|      0|         FUZZER_WRITE_AND_CRASH(#x << " = " << x << " != " << #y << " = " << y << "\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]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   61|      0|      }                                                                                  \
  |  |   62|      4|   } while(0)
  |  |  ------------------
  |  |  |  Branch (62:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
   60|       |
   61|      4|      if(ptr) {
  ------------------
  |  Branch (61:10): [True: 4, False: 0]
  ------------------
   62|      4|         pages.push_back(RawPage(ptr));
   63|      4|      }
   64|      4|   }
   65|       |
   66|      1|   return pages;
   67|      1|}
mem_pool.cpp:_ZN12_GLOBAL__N_17RawPageC2EOS0_:
   36|      4|      RawPage(RawPage&& other) : m_p(nullptr) { std::swap(m_p, other.m_p); }
mem_pool.cpp:_ZN12_GLOBAL__N_17RawPageC2EPv:
   29|      4|      RawPage(void* p) : m_p(p) {}
mem_pool.cpp:_ZN12_GLOBAL__N_17RawPageD2Ev:
   31|      8|      ~RawPage() { std::free(m_p); }
mem_pool.cpp:_ZNK12_GLOBAL__N_17RawPage3ptrEv:
   45|  4.62k|      void* ptr() const { return m_p; }
mem_pool.cpp:_ZN12_GLOBAL__N_126compute_expected_alignmentEm:
   19|   137k|size_t compute_expected_alignment(size_t plen) {
   20|   137k|   if(Botan::is_power_of_2(plen)) {
  ------------------
  |  Branch (20:7): [True: 76.5k, False: 60.6k]
  ------------------
   21|  76.5k|      return plen;
   22|  76.5k|   } else {
   23|  60.6k|      return 8;
   24|  60.6k|   }
   25|   137k|}

_ZN5Botan11Memory_PoolC2ERKNSt3__16vectorIPvNS1_9allocatorIS3_EEEEm:
  279|  1.15k|Memory_Pool::Memory_Pool(const std::vector<void*>& pages, size_t page_size) : m_page_size(page_size) {
  280|  1.15k|   m_min_page_ptr = ~static_cast<uintptr_t>(0);
  281|  1.15k|   m_max_page_ptr = 0;
  282|       |
  283|  4.62k|   for(auto page : pages) {
  ------------------
  |  Branch (283:18): [True: 4.62k, False: 1.15k]
  ------------------
  284|  4.62k|      const uintptr_t p = reinterpret_cast<uintptr_t>(page);
  285|       |
  286|  4.62k|      m_min_page_ptr = std::min(p, m_min_page_ptr);
  287|  4.62k|      m_max_page_ptr = std::max(p, m_max_page_ptr);
  288|       |
  289|  4.62k|      clear_bytes(page, m_page_size);
  290|       |#if defined(BOTAN_MEM_POOL_USE_MMU_PROTECTIONS)
  291|       |      OS::page_prohibit_access(page);
  292|       |#endif
  293|  4.62k|      m_free_pages.push_back(static_cast<uint8_t*>(page));
  294|  4.62k|   }
  295|       |
  296|       |   /*
  297|       |   Right now this points to the start of the last page, adjust it to instead
  298|       |   point to the first byte of the following page
  299|       |   */
  300|  1.15k|   m_max_page_ptr += page_size;
  301|  1.15k|}
_ZN5Botan11Memory_PoolD2Ev:
  304|  1.15k|{
  305|       |#if defined(BOTAN_MEM_POOL_USE_MMU_PROTECTIONS)
  306|       |   for(size_t i = 0; i != m_free_pages.size(); ++i) {
  307|       |      OS::page_allow_access(m_free_pages[i]);
  308|       |   }
  309|       |#endif
  310|  1.15k|}
_ZN5Botan11Memory_Pool8allocateEm:
  312|   150k|void* Memory_Pool::allocate(size_t n) {
  313|   150k|   if(n > m_page_size) {
  ------------------
  |  Branch (313:7): [True: 0, False: 150k]
  ------------------
  314|      0|      return nullptr;
  315|      0|   }
  316|       |
  317|   150k|   const size_t n_bucket = choose_bucket(n);
  318|       |
  319|   150k|   if(n_bucket > 0) {
  ------------------
  |  Branch (319:7): [True: 146k, False: 3.77k]
  ------------------
  320|   146k|      lock_guard_type<mutex_type> lock(m_mutex);
  321|       |
  322|   146k|      std::deque<Bucket>& buckets = m_buckets_for[n_bucket];
  323|       |
  324|       |      /*
  325|       |      It would be optimal to pick the bucket with the most usage,
  326|       |      since a bucket with say 1 item allocated out of it has a high
  327|       |      chance of becoming later freed and then the whole page can be
  328|       |      recycled.
  329|       |      */
  330|   146k|      for(auto& bucket : buckets) {
  ------------------
  |  Branch (330:24): [True: 76.2k, False: 77.4k]
  ------------------
  331|  76.2k|         if(uint8_t* p = bucket.alloc()) {
  ------------------
  |  Branch (331:22): [True: 69.2k, False: 6.94k]
  ------------------
  332|  69.2k|            return p;
  333|  69.2k|         }
  334|       |
  335|       |         // If the bucket is full, maybe move it to the end of the list?
  336|       |         // Otoh bucket search should be very fast
  337|  76.2k|      }
  338|       |
  339|  77.4k|      if(!m_free_pages.empty()) {
  ------------------
  |  Branch (339:10): [True: 67.9k, False: 9.44k]
  ------------------
  340|  67.9k|         uint8_t* ptr = m_free_pages[0];
  341|  67.9k|         m_free_pages.pop_front();
  342|       |#if defined(BOTAN_MEM_POOL_USE_MMU_PROTECTIONS)
  343|       |         OS::page_allow_access(ptr);
  344|       |#endif
  345|  67.9k|         buckets.push_front(Bucket(ptr, m_page_size, n_bucket));
  346|  67.9k|         void* p = buckets[0].alloc();
  347|  67.9k|         BOTAN_ASSERT_NOMSG(p != nullptr);
  ------------------
  |  |   60|  67.9k|   do {                                                                     \
  |  |   61|  67.9k|      if(!(expr))                                                           \
  |  |  ------------------
  |  |  |  Branch (61:10): [True: 0, False: 67.9k]
  |  |  ------------------
  |  |   62|  67.9k|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   63|  67.9k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (63:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  348|  67.9k|         return p;
  349|  67.9k|      }
  350|  77.4k|   }
  351|       |
  352|       |   // out of room
  353|  13.2k|   return nullptr;
  354|   150k|}
_ZN5Botan11Memory_Pool10deallocateEPvm:
  356|   109k|bool Memory_Pool::deallocate(void* p, size_t len) noexcept {
  357|       |   // Do a fast range check first, before taking the lock
  358|   109k|   const uintptr_t p_val = reinterpret_cast<uintptr_t>(p);
  359|   109k|   if(p_val < m_min_page_ptr || p_val > m_max_page_ptr) {
  ------------------
  |  Branch (359:7): [True: 0, False: 109k]
  |  Branch (359:33): [True: 0, False: 109k]
  ------------------
  360|      0|      return false;
  361|      0|   }
  362|       |
  363|   109k|   const size_t n_bucket = choose_bucket(len);
  364|       |
  365|   109k|   if(n_bucket != 0) {
  ------------------
  |  Branch (365:7): [True: 109k, False: 0]
  ------------------
  366|   109k|      try {
  367|   109k|         lock_guard_type<mutex_type> lock(m_mutex);
  368|       |
  369|   109k|         std::deque<Bucket>& buckets = m_buckets_for[n_bucket];
  370|       |
  371|   112k|         for(size_t i = 0; i != buckets.size(); ++i) {
  ------------------
  |  Branch (371:28): [True: 112k, False: 0]
  ------------------
  372|   112k|            Bucket& bucket = buckets[i];
  373|   112k|            if(bucket.free(p)) {
  ------------------
  |  Branch (373:16): [True: 109k, False: 3.86k]
  ------------------
  374|   109k|               if(bucket.empty()) {
  ------------------
  |  Branch (374:19): [True: 65.6k, False: 43.3k]
  ------------------
  375|       |#if defined(BOTAN_MEM_POOL_USE_MMU_PROTECTIONS)
  376|       |                  OS::page_prohibit_access(bucket.ptr());
  377|       |#endif
  378|  65.6k|                  m_free_pages.push_back(bucket.ptr());
  379|       |
  380|  65.6k|                  if(i != buckets.size() - 1) {
  ------------------
  |  Branch (380:22): [True: 467, False: 65.1k]
  ------------------
  381|    467|                     std::swap(buckets.back(), buckets[i]);
  382|    467|                  }
  383|  65.6k|                  buckets.pop_back();
  384|  65.6k|               }
  385|   109k|               return true;
  386|   109k|            }
  387|   112k|         }
  388|   109k|      } catch(...) {
  389|       |         /*
  390|       |         * The only exception throws that can occur in the above code are from
  391|       |         * either the STL or BOTAN_ASSERT failures. In either case, such an
  392|       |         * error indicates a logic error or data corruption in the memory
  393|       |         * allocator such that it is no longer safe to continue executing.
  394|       |         *
  395|       |         * Since this function is noexcept, simply letting the exception escape
  396|       |         * is sufficient for terminate to be called. However in this scenario
  397|       |         * it is implementation defined if any stack unwinding is performed.
  398|       |         * Since stack unwinding could cause further memory deallocations this
  399|       |         * could result in further corruption in this allocator state. To prevent
  400|       |         * this, call terminate directly.
  401|       |         */
  402|      0|         std::terminate();
  403|      0|      }
  404|   109k|   }
  405|       |
  406|      0|   return false;
  407|   109k|}
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_113choose_bucketEm:
   92|   259k|size_t choose_bucket(size_t n) {
   93|   259k|   const size_t MINIMUM_ALLOCATION = 16;
   94|   259k|   const size_t MAXIMUM_ALLOCATION = 256;
   95|       |
   96|   259k|   if(n < MINIMUM_ALLOCATION || n > MAXIMUM_ALLOCATION) {
  ------------------
  |  Branch (96:7): [True: 3.17k, False: 256k]
  |  Branch (96:33): [True: 601, False: 255k]
  ------------------
   97|  3.77k|      return 0;
   98|  3.77k|   }
   99|       |
  100|       |   // Need to tune these
  101|       |
  102|   255k|   const size_t buckets[] = {
  103|   255k|      16,
  104|   255k|      24,
  105|   255k|      32,
  106|   255k|      48,
  107|   255k|      64,
  108|   255k|      80,
  109|   255k|      96,
  110|   255k|      112,
  111|   255k|      128,
  112|   255k|      160,
  113|   255k|      192,
  114|   255k|      256,
  115|   255k|      0,
  116|   255k|   };
  117|       |
  118|  1.07M|   for(size_t i = 0; buckets[i]; ++i) {
  ------------------
  |  Branch (118:22): [True: 1.07M, False: 0]
  ------------------
  119|  1.07M|      if(n <= buckets[i]) {
  ------------------
  |  Branch (119:10): [True: 255k, False: 815k]
  ------------------
  120|   255k|         return buckets[i];
  121|   255k|      }
  122|  1.07M|   }
  123|       |
  124|      0|   return 0;
  125|   255k|}
_ZN5Botan6Bucket5allocEv:
  229|   144k|      uint8_t* alloc() {
  230|   144k|         if(m_is_full) {
  ------------------
  |  Branch (230:13): [True: 6.47k, False: 137k]
  ------------------
  231|       |            // I know I am full
  232|  6.47k|            return nullptr;
  233|  6.47k|         }
  234|       |
  235|   137k|         size_t offset;
  236|   137k|         if(!m_bitmap.find_free(&offset)) {
  ------------------
  |  Branch (236:13): [True: 476, False: 137k]
  ------------------
  237|       |            // I just found out I am full
  238|    476|            m_is_full = true;
  239|    476|            return nullptr;
  240|    476|         }
  241|       |
  242|   137k|         BOTAN_ASSERT(offset * m_item_size < m_page_size, "Offset is in range");
  ------------------
  |  |   51|   137k|   do {                                                                                 \
  |  |   52|   137k|      if(!(expr))                                                                       \
  |  |  ------------------
  |  |  |  Branch (52:10): [True: 0, False: 137k]
  |  |  ------------------
  |  |   53|   137k|         Botan::assertion_failure(#expr, assertion_made, __func__, __FILE__, __LINE__); \
  |  |   54|   137k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (54:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  243|   137k|         return m_range + m_item_size * offset;
  244|   137k|      }
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_16BitMap9find_freeEPm:
  202|   137k|bool BitMap::find_free(size_t* bit) {
  203|   155k|   for(size_t i = 0; i != m_bits.size(); ++i) {
  ------------------
  |  Branch (203:22): [True: 155k, False: 476]
  ------------------
  204|   155k|      const bitmask_type mask = (i == m_bits.size() - 1) ? m_last_mask : m_main_mask;
  ------------------
  |  Branch (204:33): [True: 58.4k, False: 96.7k]
  ------------------
  205|   155k|      if((m_bits[i] & mask) != mask) {
  ------------------
  |  Branch (205:10): [True: 137k, False: 17.9k]
  ------------------
  206|   137k|         const size_t free_bit = find_set_bit(~m_bits[i]);
  207|   137k|         const bitmask_type bmask = static_cast<bitmask_type>(1) << (free_bit % BITMASK_BITS);
  208|   137k|         BOTAN_ASSERT_NOMSG((m_bits[i] & bmask) == 0);
  ------------------
  |  |   60|   137k|   do {                                                                     \
  |  |   61|   137k|      if(!(expr))                                                           \
  |  |  ------------------
  |  |  |  Branch (61:10): [True: 0, False: 137k]
  |  |  ------------------
  |  |   62|   137k|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   63|   137k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (63:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  209|   137k|         m_bits[i] |= bmask;
  210|   137k|         *bit = BITMASK_BITS * i + free_bit;
  211|   137k|         return true;
  212|   137k|      }
  213|   155k|   }
  214|       |
  215|    476|   return false;
  216|   137k|}
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_112find_set_bitImEEmT_:
  135|   137k|size_t find_set_bit(T b) {
  136|   137k|   size_t s = 8 * sizeof(T) / 2;
  137|   137k|   size_t bit = 0;
  138|       |
  139|       |   // In this context we don't need to be const-time
  140|   960k|   while(s > 0) {
  ------------------
  |  Branch (140:10): [True: 823k, False: 137k]
  ------------------
  141|   823k|      const T mask = (static_cast<T>(1) << s) - 1;
  142|   823k|      if((b & mask) == 0) {
  ------------------
  |  Branch (142:10): [True: 141k, False: 681k]
  ------------------
  143|   141k|         bit += s;
  144|   141k|         b >>= s;
  145|   141k|      }
  146|   823k|      s /= 2;
  147|   823k|   }
  148|       |
  149|   137k|   return bit;
  150|   137k|}
_ZN5Botan6BucketC2EPhmm:
  227|  67.9k|            m_is_full(false) {}
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_16BitMapC2Em:
  154|  67.9k|      explicit BitMap(size_t bits) : m_len(bits) {
  155|  67.9k|         m_bits.resize((bits + BITMASK_BITS - 1) / BITMASK_BITS);
  156|       |         // MSVC warns if the cast isn't there, clang-tidy warns that the cast is pointless
  157|  67.9k|         m_main_mask = static_cast<bitmask_type>(~0);  // NOLINT(bugprone-misplaced-widening-cast)
  158|  67.9k|         m_last_mask = m_main_mask;
  159|       |
  160|  67.9k|         if(bits % BITMASK_BITS != 0) {
  ------------------
  |  Branch (160:13): [True: 29.7k, False: 38.2k]
  ------------------
  161|  29.7k|            m_last_mask = (static_cast<bitmask_type>(1) << (bits % BITMASK_BITS)) - 1;
  162|  29.7k|         }
  163|  67.9k|      }
_ZN5Botan6Bucket4freeEPv:
  246|   112k|      bool free(void* p) {
  247|   112k|         if(!in_this_bucket(p)) {
  ------------------
  |  Branch (247:13): [True: 3.86k, False: 109k]
  ------------------
  248|  3.86k|            return false;
  249|  3.86k|         }
  250|       |
  251|       |         /*
  252|       |         Zero also any trailing bytes, which should not have been written to,
  253|       |         but maybe the user was bad and wrote past the end.
  254|       |         */
  255|   109k|         std::memset(p, 0, m_item_size);
  256|       |
  257|   109k|         const size_t offset = (reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(m_range)) / m_item_size;
  258|       |
  259|   109k|         m_bitmap.free(offset);
  260|   109k|         m_is_full = false;
  261|       |
  262|   109k|         return true;
  263|   112k|      }
_ZNK5Botan6Bucket14in_this_bucketEPv:
  265|   112k|      bool in_this_bucket(void* p) const { return ptr_in_pool(m_range, m_page_size, p, m_item_size); }
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_111ptr_in_poolEPKvmS2_m:
  127|   112k|inline bool ptr_in_pool(const void* pool_ptr, size_t poolsize, const void* buf_ptr, size_t bufsize) {
  128|   112k|   const uintptr_t pool = reinterpret_cast<uintptr_t>(pool_ptr);
  129|   112k|   const uintptr_t buf = reinterpret_cast<uintptr_t>(buf_ptr);
  130|   112k|   return (buf >= pool) && (buf + bufsize <= pool + poolsize);
  ------------------
  |  Branch (130:11): [True: 110k, False: 2.82k]
  |  Branch (130:28): [True: 109k, False: 1.04k]
  ------------------
  131|   112k|}
mem_pool.cpp:_ZN5Botan12_GLOBAL__N_16BitMap4freeEm:
  167|   109k|      void free(size_t bit) {
  168|   109k|         BOTAN_ASSERT_NOMSG(bit <= m_len);
  ------------------
  |  |   60|   109k|   do {                                                                     \
  |  |   61|   109k|      if(!(expr))                                                           \
  |  |  ------------------
  |  |  |  Branch (61:10): [True: 0, False: 109k]
  |  |  ------------------
  |  |   62|   109k|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   63|   109k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (63:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  169|   109k|         const size_t w = bit / BITMASK_BITS;
  170|   109k|         BOTAN_ASSERT_NOMSG(w < m_bits.size());
  ------------------
  |  |   60|   109k|   do {                                                                     \
  |  |   61|   109k|      if(!(expr))                                                           \
  |  |  ------------------
  |  |  |  Branch (61:10): [True: 0, False: 109k]
  |  |  ------------------
  |  |   62|   109k|         Botan::assertion_failure(#expr, "", __func__, __FILE__, __LINE__); \
  |  |   63|   109k|   } while(0)
  |  |  ------------------
  |  |  |  Branch (63:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
  171|   109k|         const bitmask_type mask = static_cast<bitmask_type>(1) << (bit % BITMASK_BITS);
  172|   109k|         m_bits[w] = m_bits[w] & (~mask);
  173|   109k|      }
_ZNK5Botan6Bucket5emptyEv:
  267|   109k|      bool empty() const { return m_bitmap.empty(); }
mem_pool.cpp:_ZNK5Botan12_GLOBAL__N_16BitMap5emptyEv:
  175|   109k|      bool empty() const {
  176|   214k|         for(auto bitset : m_bits) {
  ------------------
  |  Branch (176:26): [True: 214k, False: 65.6k]
  ------------------
  177|   214k|            if(bitset != 0) {
  ------------------
  |  Branch (177:16): [True: 43.3k, False: 171k]
  ------------------
  178|  43.3k|               return false;
  179|  43.3k|            }
  180|   214k|         }
  181|       |
  182|  65.6k|         return true;
  183|   109k|      }
_ZNK5Botan6Bucket3ptrEv:
  269|  65.6k|      uint8_t* ptr() const { return m_range; }

