summaryrefslogtreecommitdiff
path: root/extract.h
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2017-08-18 20:11:43 -0700
committerGuy Harris <guy@alum.mit.edu>2017-08-18 20:11:43 -0700
commit141c1c6f498390820c8913408d8af6cf6e97152a (patch)
treeb87e7ece3db1dc714ca044c49aeb10f862095938 /extract.h
parent3951a87cbe09333a11faa929f93508c848a93fd5 (diff)
downloadtcpdump-141c1c6f498390820c8913408d8af6cf6e97152a.tar.gz
Suppress UBSan warnings from EXTRACT_.
Yes, the behavior of an access with an improperly-aligned pointer is undefined according to the C standard, but if we're doing that in an EXTRACT_ function/macro, we're doing it because we know it's safe and because it's faster than picking the bytes out one by one and assembling them, so suppress those warnings. Pull over libpcap's funcattrs.h and use it to do a bunch of checks for various function attributes; that defines __has_attribute(), so we can use it to check for the "suppress sanitizer warnings" attribute. While we're at it, use other things it defines to specify "this function never returns", "this function is printf-like", and "this function argument is a printf-style format argument", rather than using various configure-script checks. That should let us declare some function attributes with Microsoft Visual Studio's compilers.
Diffstat (limited to 'extract.h')
-rw-r--r--extract.h49
1 files changed, 41 insertions, 8 deletions
diff --git a/extract.h b/extract.h
index 23623c28..2ea4ca80 100644
--- a/extract.h
+++ b/extract.h
@@ -20,8 +20,41 @@
*/
/*
- * Macros to extract possibly-unaligned big-endian integral values.
+ * Inline functions or macros to extract possibly-unaligned big-endian
+ * integral values.
*/
+#include "funcattrs.h"
+
+/*
+ * If we have versions of GCC or Clang that support an __attribute__
+ * to say "if we're building with unsigned behavior sanitization,
+ * don't complain about undefined behavior in this function", we
+ * label these functions with that attribute - we *know* it's undefined
+ * in the C standard, but we *also* know it does what we want with
+ * the ISA we're targeting and the compiler we're using.
+ *
+ * For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined));
+ * pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether
+ * GCC or Clang first had __attribute__((no_sanitize(XXX)).
+ *
+ * For Clang, we check for __attribute__((no_sanitize(XXX)) with
+ * __has_attribute, as there are versions of Clang that support
+ * __attribute__((no_sanitize("undefined")) but don't support
+ * __attribute__((no_sanitize_undefined)).
+ *
+ * We define this here, rather than in funcattrs.h, because we
+ * only want it used here, we don't want it to be broadly used.
+ * (Any printer will get this defined, but this should at least
+ * make it harder for people to find.)
+ */
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
+#define UNALIGNED_OK __attribute__((no_sanitize_undefined))
+#elif __has_attribute(no_sanitize)
+#define UNALIGNED_OK __attribute__((no_sanitize("undefined")))
+#else
+#define UNALIGNED_OK
+#endif
+
#ifdef LBL_ALIGN
/*
* The processor doesn't natively handle unaligned loads.
@@ -31,7 +64,7 @@
defined(__mips) || defined(__mips__))
/*
- * This is a GCC-compatible compiler and we have __attribute__, which
+* This is a GCC-compatible compiler and we have __attribute__, which
* we assume that mean we have __attribute__((packed)), and this is
* MIPS or Alpha, which has instructions that can help when doing
* unaligned loads.
@@ -88,19 +121,19 @@ typedef struct {
uint32_t val;
} __attribute__((packed)) unaligned_uint32_t;
-static inline uint16_t
+UNALIGNED_OK static inline uint16_t
EXTRACT_16BITS(const void *p)
{
return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
}
-static inline uint32_t
+UNALIGNED_OK static inline uint32_t
EXTRACT_32BITS(const void *p)
{
return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
}
-static inline uint64_t
+UNALIGNED_OK static inline uint64_t
EXTRACT_64BITS(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
@@ -138,19 +171,19 @@ EXTRACT_64BITS(const void *p)
* The processor natively handles unaligned loads, so we can just
* cast the pointer and fetch through it.
*/
-static inline uint16_t
+static inline uint16_t UNALIGNED_OK
EXTRACT_16BITS(const void *p)
{
return ((uint16_t)ntohs(*(const uint16_t *)(p)));
}
-static inline uint32_t
+static inline uint32_t UNALIGNED_OK
EXTRACT_32BITS(const void *p)
{
return ((uint32_t)ntohl(*(const uint32_t *)(p)));
}
-static inline uint64_t
+static inline uint64_t UNALIGNED_OK
EXTRACT_64BITS(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |