diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-03-28 11:38:41 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-03-28 12:35:52 +0000 |
commit | f0f199001503b8f649a0cbb44261657f1bfd0cb3 (patch) | |
tree | f203b56320597797607d42276500246ed97dd9d7 /document | |
parent | f586464b27375f090d85b030bd8294fd2db51de2 (diff) |
Handle unaligned IdString reads in a well-defined manner
Should compile down to effectively the same instructions on x86-64,
and might save us some headaches on architectures that are less lenient
with data alignment for reads.
Diffstat (limited to 'document')
-rw-r--r-- | document/src/vespa/document/base/idstring.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/document/src/vespa/document/base/idstring.cpp b/document/src/vespa/document/base/idstring.cpp index a364ffd90ce..f3e41981c8e 100644 --- a/document/src/vespa/document/base/idstring.cpp +++ b/document/src/vespa/document/base/idstring.cpp @@ -110,13 +110,27 @@ fmemchr(const char * s, const char * e) #endif } +namespace { + +// Avoid issues with primitive alignment when reading from buffer. +// Requires caller to ensure buffer is big enough to read from. +template <typename T> +inline T read_unaligned(const char* buf) noexcept +{ + T tmp; + memcpy(&tmp, buf, sizeof(T)); + return tmp; +} + +} + void verifyIdString(const char * id, size_t sz_) { if (sz_ > 4) { - if (_G_id.as16 == *reinterpret_cast<const uint16_t *>(id) && id[2] == ':') { + if ((_G_id.as16 == read_unaligned<uint16_t>(id)) && (id[2] == ':')) { return; - } else if ((sz_ == 6) && (_G_null.as32 == *reinterpret_cast<const uint32_t *>(id)) && (id[4] == ':') && (id[5] == ':')) { + } else if ((sz_ == 6) && (_G_null.as32 == read_unaligned<uint32_t>(id)) && (id[4] == ':') && (id[5] == ':')) { reportNoId(id); } else if (sz_ > 8) { reportNoSchemeSeparator(id); |