diff options
author | Michael Biebl <mbiebl@gmail.com> | 2016-07-27 05:32:37 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-07-26 23:32:37 -0400 |
commit | b6b609dbc202e5645fc58e87b8a7d46426ee4bb7 (patch) | |
tree | 6bb47c6c386bffcb1de3b12a24aaa335c0e4d3ca | |
parent | 5a8ff0e61dd8094b2b5d0b35df2ca13b489e0dfa (diff) |
string-util: rework memory_erase() to not use GCC optimize attribute (#3812)
"#pragma GCC optimize" is merely a convenience to decorate multiple
functions with attribute optimize. And the manual has this to say about
this attribute:
This attribute should be used for debugging purposes only. It
is not suitable in production code.
Some versions of GCC also seem to have a problem with this pragma in
combination with LTO, resulting in ICEs.
So use a different approach (indirect the memset call via a volatile
function pointer) as implemented in openssl's crypto/mem_clr.c.
Closes: #3811
-rw-r--r-- | src/basic/string-util.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/src/basic/string-util.c b/src/basic/string-util.c index e9856b90d3..5d4510e1b3 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -22,6 +22,7 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "alloc-util.h" #include "gunicode.h" @@ -822,25 +823,20 @@ int free_and_strdup(char **p, const char *s) { return 1; } -#pragma GCC push_options -#pragma GCC optimize("O0") +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + * This approach is inspired by openssl's crypto/mem_clr.c. + */ +typedef void *(*memset_t)(void *,int,size_t); -void* memory_erase(void *p, size_t l) { - volatile uint8_t* x = (volatile uint8_t*) p; - - /* This basically does what memset() does, but hopefully isn't - * optimized away by the compiler. One of those days, when - * glibc learns memset_s() we should replace this call by - * memset_s(), but until then this has to do. */ - - for (; l > 0; l--) - *(x++) = 'x'; +static volatile memset_t memset_func = memset; - return p; +void* memory_erase(void *p, size_t l) { + return memset_func(p, 'x', l); } -#pragma GCC pop_options - char* string_erase(char *x) { if (!x) |