Force `Rep` size to be at least 8 bytes when running under a sanitizer

Sanitizers are picky for container start addresses to be aligned at 8 byte aligned offsets, which causes issues under 32 bit compilations as we lay out the internal layout as {arena*, elements[...]}. This change forces the minimum header size to be at least 8 bytes, adding padding as needed.

PiperOrigin-RevId: 527596133
pull/12573/head
Martijn Vels 2 years ago committed by Copybara-Service
parent a1b6dd9247
commit c224676c2d
  1. 18
      src/google/protobuf/repeated_field.h

@ -423,17 +423,17 @@ class RepeatedField final
return prev_size; return prev_size;
} }
// Pad the Rep after arena allow for power-of-two byte sizes when // Pad the rep to being max(Arena*, Element) with a minimum align
// sizeof(Element) > sizeof(Arena*). eg for 16-byte objects. // of 8 as sanitizers are picky on the alignment of containers to
static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize = // start at 8 byte offsets even when compiling for 32 bit platforms.
sizeof(Arena*) < sizeof(Element) ? sizeof(Element) : sizeof(Arena*);
struct Rep { struct Rep {
Arena* arena; union {
Element* elements() { alignas(8) Arena* arena;
return reinterpret_cast<Element*>(reinterpret_cast<char*>(this) + Element unused;
kRepHeaderSize); };
} Element* elements() { return reinterpret_cast<Element*>(this + 1); }
}; };
static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize = sizeof(Rep);
// If total_size_ == 0 this points to an Arena otherwise it points to the // If total_size_ == 0 this points to an Arena otherwise it points to the
// elements member of a Rep struct. Using this invariant allows the storage of // elements member of a Rep struct. Using this invariant allows the storage of

Loading…
Cancel
Save