1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-25 06:03:40 +03:00

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
This commit is contained in:
Michael Biebl 2016-07-27 05:32:37 +02:00 committed by Zbigniew Jędrzejewski-Szmek
parent 5a8ff0e61d
commit b6b609dbc2

View File

@ -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);
static volatile memset_t memset_func = memset;
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';
return p;
return memset_func(p, 'x', l);
}
#pragma GCC pop_options
char* string_erase(char *x) {
if (!x)