You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following piece of code leads to panic (sometimes):
sol::state lua;
lua["test"] = Test {};
// [sol2] An error occurred and panic has been invoked: aligned allocation of userdata block (data section) for 'Test' failed
I've made some research and found the following
The first problem is that misaligned_size can be less than aligned_size:
where align_space_for calculates memory size required to place correctly aligned types in memory block starting at specific address.
align_space_for<Test*, Test>((void*)0x0) == 16 (or even 12, see below)
align_space_for<Test*, Test>((void*)0x1) == 15
Technically, 0x0 is the best alignment for Test* (first type in pack). However, the second type (Test) would be placed at minimal address equal to 0x4 or 0x05 but requires 0x8 alignment so there would be a 3-4 byte gap. This means that align_space_for<...>((void*)0x0) doesn't calculate required space for best™ allocator and align_space_for<..>((void*)0x1) - for the worst™ one. More specifically, the worst case for Test is reached when allocator returns pointer with representation 0xXXXXX5: align_space_for<Test*, Test>((void*)0x5) == 19.
The second problem is the attempt to avoid UB, leading to randomization of the result.
First of all, there is an UB for (void*)0x1anyway. Just because (void*)0x1 is invalid address and is not nullptr so alignment_shim won't help.
Secondly, align_space_for<Test*, Test>(nullptr) may return 16 or 12 or something else depending on address of a local variable alignment_shim:
reinterpret_cast<std::uintptr_t>(&alignment_shim[0]) % 16 == 0 => result is 16
reinterpret_cast<std::uintptr_t>(&alignment_shim[0]) % 16 == 8 => result is 12
and so on..
In my case initial_size is 12, misaligned_size is 15 but allocator returns pointer with alignment equal to 16 requiring at least 16 bytes to place Test* and Test types.
Hello!
I've found a non-obvious bug in alignment and memory size calculations. Let's take a simple type (assuming x86 build mode):
The following piece of code leads to panic (sometimes):
I've made some research and found the following
The first problem is that
misaligned_size
can be less thanaligned_size
:sol2/include/sol/stack_core.hpp
Lines 344 to 345 in f92c28b
where
align_space_for
calculates memory size required to place correctly aligned types in memory block starting at specific address.align_space_for<Test*, Test>((void*)0x0) == 16
(or even 12, see below)align_space_for<Test*, Test>((void*)0x1) == 15
Technically,
0x0
is the best alignment forTest*
(first type in pack). However, the second type (Test
) would be placed at minimal address equal to0x4
or0x05
but requires0x8
alignment so there would be a 3-4 byte gap. This means thatalign_space_for<...>((void*)0x0)
doesn't calculate required space for best™ allocator andalign_space_for<..>((void*)0x1)
- for the worst™ one. More specifically, the worst case forTest
is reached when allocator returns pointer with representation0xXXXXX5
:align_space_for<Test*, Test>((void*)0x5) == 19
.The second problem is the attempt to avoid UB, leading to randomization of the result.
sol2/include/sol/stack_core.hpp
Lines 109 to 117 in f92c28b
First of all, there is an UB for
(void*)0x1
anyway. Just because(void*)0x1
is invalid address and is notnullptr
soalignment_shim
won't help.Secondly,
align_space_for<Test*, Test>(nullptr)
may return16
or12
or something else depending on address of a local variablealignment_shim
:reinterpret_cast<std::uintptr_t>(&alignment_shim[0]) % 16 == 0
=> result is16
reinterpret_cast<std::uintptr_t>(&alignment_shim[0]) % 16 == 8
=> result is12
In my case
initial_size
is12
,misaligned_size
is15
but allocator returns pointer with alignment equal to16
requiring at least16
bytes to placeTest*
andTest
types.Tested sol2 version: trunk (f92c28b)
P.S. I'm already working on PR. Hope, you'll accept it.
The text was updated successfully, but these errors were encountered: