[CRIU] [PATCH] string.h: fix memset over-optimization with clang

Kir Kolyshkin kir at openvz.org
Fri Jan 27 08:01:08 PST 2017


We found a weird case of parasite code dying of SIGSEGV when clang
is used as a compiler (see [1] for more details).

Apparently, it was caused by clang optimizing our builtin_memset()
by inserting a call to memset(). It is a valid compiler optimization,
aside from the fact that in our code memset() is defined as a weak
alias to builtin_memset(), which of course lead to infinite recursion
and stack growth.

This might be a bug in compiler, but there are ways to avoid it:

1. Rewrite builtin_memset() in asm (note it needs to be done
   for every architecture supported).
2. Disable compiler optimizations for this code (say, by using -O0).
3. Declare the pointer inside builtin_memcpy() as volatile.

The last approach looks more appealing -- mostly for being simple.

[1] https://github.com/xemul/criu/issues/279

Cc: Andrei Vagin <avagin at virtuozzo.com>
Cc: Dmitry Safonov <dsafonov at virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Kir Kolyshkin <kir at openvz.org>
---
 criu/include/asm-generic/string.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/criu/include/asm-generic/string.h b/criu/include/asm-generic/string.h
index ff91968..6e0f659 100644
--- a/criu/include/asm-generic/string.h
+++ b/criu/include/asm-generic/string.h
@@ -65,7 +65,7 @@ static always_inline int builtin_strncmp(const char *cs, const char *ct, size_t
 #ifndef HAS_BUILTIN_MEMSET
 static __maybe_unused void *builtin_memset(void *s, const int c, size_t count)
 {
-	char *dest = s;
+	volatile char *dest = s;
 	size_t i = 0;
 
 	while (i < count)
-- 
2.9.3



More information about the CRIU mailing list