mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
AK: Apply empty base optimization to Variant on Windows
On the MSVC ABI (used by clang-cl), each empty base class is given a
unique address with 1 byte of padding by default. Variant inherits from
a deep chain of empty base classes (InheritFromPacks ->
InheritFromUniqueEntries -> VariantConstructors) for its inherited
constructor mechanism. Without __declspec(empty_bases), the pointer
adjustment in VariantConstructors::internal_cast() from the
VariantConstructors subobject back to the Variant base was computed
incorrectly due to accumulated padding, causing the constructor to write
m_data and m_index at wrong offsets and corrupting the stored object.
This manifested as heap corruption (STATUS_HEAP_CORRUPTION 0xc0000374)
whenever a Variant containing a large type (e.g. ByteCode at 240 bytes)
was destroyed after being constructed through the inherited constructor
path. In practice this crashed `new RegExp('a')` in LibJS on Windows,
preventing ~880 of ~1058 LibJS runtime tests from running.
This commit is contained in:
committed by
Alexander Kalenik
parent
1d025620e3
commit
70a1a9e82f
Notes:
github-actions[bot]
2026-03-24 23:59:03 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/70a1a9e82f5 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8608
@@ -191,7 +191,7 @@ struct InheritFromUniqueEntries;
|
||||
// as that has already been checked before.
|
||||
// This makes sure that the search is linear in time (like the 'merge' step of merge sort).
|
||||
template<size_t I, typename... Ts, size_t... Js, typename... Qs>
|
||||
struct InheritFromUniqueEntries<I, ParameterPack<Ts...>, IndexSequence<Js...>, Qs...>
|
||||
struct AK_COMPACT_EMPTY_BASES InheritFromUniqueEntries<I, ParameterPack<Ts...>, IndexSequence<Js...>, Qs...>
|
||||
: public BlankIfDuplicate<Ts, Conditional<Js <= I, ParameterPack<>, Qs>...>... {
|
||||
|
||||
using BlankIfDuplicate<Ts, Conditional<Js <= I, ParameterPack<>, Qs>...>::BlankIfDuplicate...;
|
||||
@@ -203,7 +203,7 @@ struct InheritFromPacks;
|
||||
// InheritFromPacks will attempt to 'merge' the pack 'Ps' with *itself*, but skip the duplicate entries
|
||||
// (via InheritFromUniqueEntries).
|
||||
template<size_t... Is, typename... Ps>
|
||||
struct InheritFromPacks<IndexSequence<Is...>, Ps...>
|
||||
struct AK_COMPACT_EMPTY_BASES InheritFromPacks<IndexSequence<Is...>, Ps...>
|
||||
: public InheritFromUniqueEntries<Is, Ps, IndexSequence<Is...>, Ps...>... {
|
||||
|
||||
using InheritFromUniqueEntries<Is, Ps, IndexSequence<Is...>, Ps...>::InheritFromUniqueEntries...;
|
||||
@@ -225,7 +225,7 @@ template<typename T>
|
||||
concept NotLvalueReference = !IsLvalueReference<T>;
|
||||
|
||||
template<NotLvalueReference... Ts>
|
||||
struct Variant
|
||||
struct AK_COMPACT_EMPTY_BASES Variant
|
||||
: public Detail::MergeAndDeduplicatePacks<Detail::VariantConstructors<Ts, Variant<Ts...>>...> {
|
||||
public:
|
||||
using IndexType = Conditional<(sizeof...(Ts) < 255), u8, size_t>; // Note: size+1 reserved for internal value checks
|
||||
|
||||
Reference in New Issue
Block a user