From ec2204f435c7a37b3a40430a3964d86120e1b385 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 22 Jan 2016 16:01:24 -0600 Subject: [PATCH] Use volatile to keep ct_memcmp() ct --- lib/roken/ct.c | 22 ++++++++++++++++++++-- lib/roken/roken-common.h | 4 +++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/roken/ct.c b/lib/roken/ct.c index 0778c2d47..79f312d8d 100644 --- a/lib/roken/ct.c +++ b/lib/roken/ct.c @@ -42,6 +42,12 @@ * ct_memcmp() can't be used to order memory regions like memcmp(), * for example, use ct_memcmp() with qsort(). * + * We use volatile to avoid optimizations where the compiler and/or + * linker turn this ct_memcmp() into a plain memcmp(). The pointers + * themselves are also marked volatile (not just the memory pointed at) + * because in some GCC versions there is a bug which can be worked + * around by doing this. + * * @param p1 memory region 1 to compare * @param p2 memory region 2 to compare * @param len length of memory @@ -52,9 +58,21 @@ */ int -ct_memcmp(const void *p1, const void *p2, size_t len) +ct_memcmp(const volatile void * volatile p1, + const volatile void * volatile p2, + size_t len) { - const unsigned char *s1 = p1, *s2 = p2; + /* + * There's no need for s1 and s2 to be volatile; only p1 and p2 have + * to be in order to work around GCC bugs. + * + * However, s1 and s2 do have to point to volatile, as we don't know + * if the object was originally defined as volatile, and if it was + * then we'd get undefined behavior here if s1/s2 were declared to + * point to non-volatile memory. + */ + const volatile unsigned char *s1 = p1; + const volatile unsigned char *s2 = p2; size_t i; int r = 0; diff --git a/lib/roken/roken-common.h b/lib/roken/roken-common.h index 8221c2a76..6f50c9a31 100644 --- a/lib/roken/roken-common.h +++ b/lib/roken/roken-common.h @@ -507,7 +507,9 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rk_cloexec_socket(rk_socket_t); ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL -ct_memcmp(const void *, const void *, size_t); +ct_memcmp(const volatile void * volatile, + const volatile void * volatile, + size_t); void ROKEN_LIB_FUNCTION rk_random_init(void);