Opened 6 years ago

Closed 6 years ago

#12401 closed Bugs (invalid)

UB when sizeof(std::size_t) in floor_log2

Reported by: viboes Owned by: Ion Gaztañaga
Milestone: To Be Determined Component: intrusive
Version: Boost 1.61.0 Severity: Problem
Keywords: Cc:

Description

The line

      v |= v >> 32; // (*)

in the following function, should fall in UB, when the sizeof(std::size_t) is 4, isn't it?

   inline std::size_t floor_log2 (std::size_t v, integral_constant<std::size_t, 64>)
   {
      static const std::size_t MultiplyDeBruijnBitPosition[64] = {
      63,  0, 58,  1, 59, 47, 53,  2,
      60, 39, 48, 27, 54, 33, 42,  3,
      61, 51, 37, 40, 49, 18, 28, 20,
      55, 30, 34, 11, 43, 14, 22,  4,
      62, 57, 46, 52, 38, 26, 32, 41,
      50, 36, 17, 19, 29, 10, 13, 21,
      56, 45, 25, 31, 35, 16,  9, 12,
      44, 24, 15,  8, 23,  7,  6,  5};

      v |= v >> 1;
      v |= v >> 2;
      v |= v >> 4;
      v |= v >> 8;
      v |= v >> 16;
      v |= v >> 32; // (*)
      return MultiplyDeBruijnBitPosition[((std::size_t)((v - (v >> 1))*0x07EDD5E59A4E28C2ULL)) >> 58];
}

Change History (1)

comment:1 by Ion Gaztañaga, 6 years ago

Resolution: invalid
Status: newclosed

That function is only called if sizeof(std::size_t)*CHAR_BIT is 64:

   inline std::size_t floor_log2 (std::size_t x)
   {
      const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
      return floor_log2(x, integral_constant<std::size_t, Bits>());
   }

The 32 bit version uses only 16 bit shift:

   inline std::size_t floor_log2 (std::size_t v, integral_constant<std::size_t, 32>)
   {
      static const int MultiplyDeBruijnBitPosition[32] =
      {
         0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
         8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
      };

      v |= v >> 1;
      v |= v >> 2;
      v |= v >> 4;
      v |= v >> 8;
      v |= v >> 16;

      return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27];
   }

Note: See TracTickets for help on using tickets.