@@ -298,6 +298,33 @@ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
298298}
299299#else /* BROTLI_ALIGNED_READ */
300300/* Unaligned memory access is allowed: just cast pointer to requested type. */
301+ #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
302+ defined (MEMORY_SANITIZER)
303+ /* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
304+ AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
305+ will miss a bug if 08 is the first unaddressable byte.
306+ ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
307+ miss a race between this access and some other accesses to 08.
308+ MemorySanitizer will correctly propagate the shadow on unaligned stores
309+ and correctly report bugs on unaligned loads, but it may not properly
310+ update and report the origin of the uninitialized memory.
311+ For all three tools, replacing an unaligned access with a tool-specific
312+ callback solves the problem. */
313+ #if defined(__cplusplus)
314+ extern " C" {
315+ #endif /* __cplusplus */
316+ uint16_t __sanitizer_unaligned_load16 (const void * p);
317+ uint32_t __sanitizer_unaligned_load32 (const void * p);
318+ uint64_t __sanitizer_unaligned_load64 (const void * p);
319+ void __sanitizer_unaligned_store64 (void * p, uint64_t v);
320+ #if defined(__cplusplus)
321+ } /* extern "C" */
322+ #endif /* __cplusplus */
323+ #define BrotliUnalignedRead16 __sanitizer_unaligned_load16
324+ #define BrotliUnalignedRead32 __sanitizer_unaligned_load32
325+ #define BrotliUnalignedRead64 __sanitizer_unaligned_load64
326+ #define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
327+ #else
301328static BROTLI_INLINE uint16_t BrotliUnalignedRead16 (const void * p) {
302329 return *(const uint16_t *)p;
303330}
@@ -316,14 +343,14 @@ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
316343/* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
317344
318345#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
319- typedef __attribute__ ((aligned(1 ))) uint64_t unaligned_uint64_t ;
346+ typedef __attribute__ ((aligned(1 ))) uint64_t brotli_unaligned_uint64_t ;
320347
321348static BROTLI_INLINE uint64_t BrotliUnalignedRead64 (const void * p) {
322- return (uint64_t ) ((unaligned_uint64_t *) p)[0 ];
349+ return (uint64_t ) ((brotli_unaligned_uint64_t *) p)[0 ];
323350}
324351static BROTLI_INLINE void BrotliUnalignedWrite64 (void * p, uint64_t v) {
325- unaligned_uint64_t * dwords = (unaligned_uint64_t *) p;
326- dwords[0 ] = (unaligned_uint64_t ) v;
352+ brotli_unaligned_uint64_t * dwords = (brotli_unaligned_uint64_t *) p;
353+ dwords[0 ] = (brotli_unaligned_uint64_t ) v;
327354}
328355#else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
329356static BROTLI_INLINE uint64_t BrotliUnalignedRead64 (const void * p) {
@@ -337,6 +364,7 @@ static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
337364}
338365#endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
339366#endif /* BROTLI_64_BITS */
367+ #endif /* ASAN / TSAN / MSAN */
340368#endif /* BROTLI_ALIGNED_READ */
341369
342370#if BROTLI_LITTLE_ENDIAN
0 commit comments