summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsimd.cpp
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-03-06 19:34:06 +0100
committerMarc Mutz <marc.mutz@kdab.com>2016-03-09 13:16:19 +0000
commit1bfc7f680fc3dd839eac553c80d151a2cc7bfa3d (patch)
tree863d4f81a6febab1a67cbf203ac0122da2d8d53d /src/corelib/tools/qsimd.cpp
parent1b441c3941efc56f9b0ead35a4501056a74a77e1 (diff)
QString, QJson, QHash: Fix UBs involving unaligned loads
Found by UBSan: src/corelib/tools/qstring.cpp:587:42: runtime error: load of misaligned address 0x2acbf4b7551b for type 'const long long int', which requires 8 byte alignment src/corelib/json/qjson_p.h:405:30: runtime error: store to misaligned address 0x0000019b1e52 for type 'quint64', which requires 8 byte alignment src/corelib/tools/qhash.cpp:116:27: runtime error: load of misaligned address 0x2b8f9ce80e85 for type 'const qlonglong', which requires 8 byte alignment src/corelib/tools/qhash.cpp:133:26: runtime error: load of misaligned address 0x2b8f9ce80e8d for type 'const ushort', which requires 2 byte alignment Fix by memcpy()ing into a local variable. Wrap this trick in template functions in qsimd_p.h. These are marked as always- inline and use __builtin_memcpy() where available in an attempt to avoid the memcpy() function call overhead in debug builds. While this looks prohibitively expensive, from the pov of the C++ abstract machine, it is 100% equivalent, except for the absence of undefined behavior. In one case, the cast produces a local temporary which is then copied into the function, and in the other case, that local variable comes from return value of qUnalignedLoad(). Consequently, GCC compiles these two versions into identical assembler code (only verfied for ucstrncmp, but there's no reason to believe that it wouldn't hold for the other cases, too). Task-number: QTBUG-51651 Change-Id: Ia50d4a1d7580b6f803e0895c9f3d89c7da37840c Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Diffstat (limited to 'src/corelib/tools/qsimd.cpp')
-rw-r--r--src/corelib/tools/qsimd.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index f07eb098f2..5ca2ce4c6f 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -716,4 +716,26 @@ void qDumpCPUFeatures()
puts("");
}
+/*!
+ \internal
+ \fn T qUnalignedLoad(const void *ptr)
+ \since 5.6.1
+
+ Loads a \c{T} from address \a ptr, which may be misaligned.
+
+ Use of this function avoid the undefined behavior that the C++ standard
+ otherwise attributes to unaligned loads.
+*/
+
+/*!
+ \internal
+ \fn void qUnalignedStore(void *ptr, T t)
+ \since 5.6.1
+
+ Stores \a t to address \a ptr, which may be misaligned.
+
+ Use of this function avoid the undefined behavior that the C++ standard
+ otherwise attributes to unaligned stores.
+*/
+
QT_END_NAMESPACE