aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/rapidjson/rapidjson/0001-Fix-SIGBUS-due-to-unaligned-access.patch
blob: 0299fc81a0275827c0842915f3feeba0a2075473 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
From 748a652f04cd3a202ce3639770238bd9473b300c Mon Sep 17 00:00:00 2001
From: Veselin Georgiev <veselin.georgiev@garmin.com>
Date: Fri, 27 Jul 2018 13:33:09 -0500
Subject: [PATCH] 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 <veselin.georgiev@garmin.com>
Signed-off-by: Joshua Watt <Joshua.Watt@garmin.com>
Upstream-Status: Accepted 748a652f04cd3a202ce3639770238bd9473b300c
---
 include/rapidjson/rapidjson.h    |  9 ++-------
 test/unittest/allocatorstest.cpp | 26 ++++++++++++--------------
 2 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h
index a256c86e7..8cff38c2d 100644
--- a/include/rapidjson/rapidjson.h
+++ b/include/rapidjson/rapidjson.h
@@ -269,16 +269,11 @@
 /*! \ingroup RAPIDJSON_CONFIG
     \param x pointer to align
 
-    Some machines require strict data alignment. Currently the default uses 4 bytes
-    alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
+    Some machines require strict data alignment. The default is 8 bytes.
     User can customize by defining the RAPIDJSON_ALIGN function macro.
 */
 #ifndef RAPIDJSON_ALIGN
-#if RAPIDJSON_64BIT == 1
-#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
-#else
-#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
-#endif
+#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp
index a5958de19..2202c11f6 100644
--- a/test/unittest/allocatorstest.cpp
+++ b/test/unittest/allocatorstest.cpp
@@ -63,23 +63,21 @@ TEST(Allocator, MemoryPoolAllocator) {
 }
 
 TEST(Allocator, Alignment) {
-#if RAPIDJSON_64BIT == 1
-    EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0));
-    for (uint64_t i = 1; i < 8; i++) {
-        EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i));
-        EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i));
-        EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i));
-        EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i));
+    if (sizeof(size_t) >= 8) {
+        EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0));
+        for (uint64_t i = 1; i < 8; i++) {
+            EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i));
+            EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i));
+            EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i));
+            EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i));
+        }
     }
-#else
+
     EXPECT_EQ(0u, RAPIDJSON_ALIGN(0u));
-    for (uint32_t i = 1; i < 4; i++) {
-        EXPECT_EQ(4u, RAPIDJSON_ALIGN(i));
-        EXPECT_EQ(8u, RAPIDJSON_ALIGN(4u + i));
-        EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF4u + i));
-        EXPECT_EQ(0xFFFFFFFCu, RAPIDJSON_ALIGN(0xFFFFFFF8u + i));
+    for (uint32_t i = 1; i < 8; i++) {
+        EXPECT_EQ(8u, RAPIDJSON_ALIGN(i));
+        EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF0u + i));
     }
-#endif
 }
 
 TEST(Allocator, Issue399) {