Skip to content

Commit 748a652

Browse files
vgeorgievJoshuaWatt
authored andcommitted
Fix SIGBUS due to unaligned access
Update RAPIDJSON_ALIGN() to always align on an 8-byte boundary unless otherwise overridden. On some platforms (such as ARM), 64-bit items (such as doubles and 64-bit integers) must be aligned to an 8 byte address, even though the architecture is only 32-bits. On these platforms, MemoryPoolAllocator must match the malloc() behavior and return a 8 byte aligned allocation. This eliminates any alignment issues that may occur at the expense of additional memory overhead. Failure to do so caused a SIGBUS signal when calling GenericValue::SetNull(). The size of the data_ member of the GenericValue class is 16 bytes in 32-bit mode and its constructor requires an 8-byte aligned access. While parsing a JSON formatted string using Document::ParseStream(), a stack object containing GenericValue items was constructed. Since the stack was 8-byte aligned, the constructor calls would succeed. When the lifetime of the object ends, SetObjectRaw() is invoked. This triggered an allocation with 4-byte alignment to which the previously 8-byte aligned GenericValue array was copied. After this, any call to a GenericValue API that triggered the constructor and thus the placement new operation on the Data type member would trigger a SIGBUS. Signed-off-by: Veselin Georgiev <[email protected]> Signed-off-by: Joshua Watt <[email protected]>
1 parent 2bbd33b commit 748a652

File tree

2 files changed

+14
-21
lines changed

2 files changed

+14
-21
lines changed

include/rapidjson/rapidjson.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,16 +269,11 @@
269269
/*! \ingroup RAPIDJSON_CONFIG
270270
\param x pointer to align
271271
272-
Some machines require strict data alignment. Currently the default uses 4 bytes
273-
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
272+
Some machines require strict data alignment. The default is 8 bytes.
274273
User can customize by defining the RAPIDJSON_ALIGN function macro.
275274
*/
276275
#ifndef RAPIDJSON_ALIGN
277-
#if RAPIDJSON_64BIT == 1
278-
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
279-
#else
280-
#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
281-
#endif
276+
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
282277
#endif
283278

284279
///////////////////////////////////////////////////////////////////////////////

test/unittest/allocatorstest.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,23 +63,21 @@ TEST(Allocator, MemoryPoolAllocator) {
6363
}
6464

6565
TEST(Allocator, Alignment) {
66-
#if RAPIDJSON_64BIT == 1
67-
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0));
68-
for (uint64_t i = 1; i < 8; i++) {
69-
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i));
70-
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i));
71-
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i));
72-
EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i));
66+
if (sizeof(size_t) >= 8) {
67+
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0));
68+
for (uint64_t i = 1; i < 8; i++) {
69+
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i));
70+
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i));
71+
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i));
72+
EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i));
73+
}
7374
}
74-
#else
75+
7576
EXPECT_EQ(0u, RAPIDJSON_ALIGN(0u));
76-
for (uint32_t i = 1; i < 4; i++) {
77-
EXPECT_EQ(4u, RAPIDJSON_ALIGN(i));
78-
EXPECT_EQ(8u, RAPIDJSON_ALIGN(4u + i));
79-
EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF4u + i));
80-
EXPECT_EQ(0xFFFFFFFCu, RAPIDJSON_ALIGN(0xFFFFFFF8u + i));
77+
for (uint32_t i = 1; i < 8; i++) {
78+
EXPECT_EQ(8u, RAPIDJSON_ALIGN(i));
79+
EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF0u + i));
8180
}
82-
#endif
8381
}
8482

8583
TEST(Allocator, Issue399) {

0 commit comments

Comments
 (0)