From: Guy Harris Date: Mon, 2 Mar 2015 21:25:12 +0000 (-0800) Subject: C compilers can, and some do, optimize away pointer underflow checks. X-Git-Tag: tcpdump-4.7.2~1^2~16 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/09b639add17c21a1cce31a1c48a3b95198e0c15b C compilers can, and some do, optimize away pointer underflow checks. Cast the pointers to uintptr_t; use AC_TYPE_UINTPTR_T to get uintptr_t defined on older platforms that don't define it themselves. --- diff --git a/config.h.in b/config.h.in index 11ce977b..914289a8 100644 --- a/config.h.in +++ b/config.h.in @@ -217,6 +217,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if the system has the type `uintptr_t'. */ +#undef HAVE_UINTPTR_T + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H @@ -388,3 +391,7 @@ /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef uint8_t + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +#undef uintptr_t diff --git a/configure b/configure index 293edb14..43b3068a 100755 --- a/configure +++ b/configure @@ -6997,6 +6997,48 @@ _ACEOF esac +# +# Make sure we have a definition for C99's uintptr_t (regardless of +# whether the environment is a C99 environment or not). +# + + ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" +if test "x$ac_cv_type_uintptr_t" = xyes; then : + +$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h + +else + for ac_type in 'unsigned int' 'unsigned long int' \ + 'unsigned long long int'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +cat >>confdefs.h <<_ACEOF +#define uintptr_t $ac_type +_ACEOF + + ac_type= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test -z "$ac_type" && break + done +fi + + + # # Define the old BSD specified-width types in terms of the C99 types; # we may need them with libpcap include files. diff --git a/configure.in b/configure.in index 1f10dc5e..a629559e 100644 --- a/configure.in +++ b/configure.in @@ -968,6 +968,12 @@ AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T +# +# Make sure we have a definition for C99's uintptr_t (regardless of +# whether the environment is a C99 environment or not). +# +AC_TYPE_UINTPTR_T + # # Define the old BSD specified-width types in terms of the C99 types; # we may need them with libpcap include files. diff --git a/netdissect.h b/netdissect.h index 515d839d..4580e73d 100644 --- a/netdissect.h +++ b/netdissect.h @@ -258,9 +258,21 @@ struct netdissect_options { * "l" isn't so large that "ndo->ndo_snapend - (l)" underflows. * * The check is for <= rather than < because "l" might be 0. + * + * We cast the pointers to uintptr_t to make sure that the compiler + * doesn't optimize away any of these tests (which it is allowed to + * do, as adding an integer to, or subtracting an integer from, a + * pointer assumes that the pointer is a pointer to an element of an + * array and that the result of the addition or subtraction yields a + * pointer to another member of the array, so that, for example, if + * you subtract a positive integer from a pointer, the result is + * guaranteed to be less than the original pointer value). See + * + * http://www.kb.cert.org/vuls/id/162289 */ -#define ND_TTEST2(var, l) (ndo->ndo_snapend - (l) <= ndo->ndo_snapend && \ - (const u_char *)&(var) <= ndo->ndo_snapend - (l)) +#define ND_TTEST2(var, l) \ + ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \ + (uintptr_t)&(var) <= (uintptr_t)ndo->ndo_snapend - (l)) /* True if "var" was captured */ #define ND_TTEST(var) ND_TTEST2(var, sizeof(var))