Forcing memset to be executed against compiler optimization

15 Aug 2020 - John Z. Li

With following code

    char a[10];
    scanf("%9s", a);
    printf("%s\n", a); // changed to puts by the compilers
    memset(a, 0, sizeof a); // REMOVED by the compilers

if turning on compiler optimization with -O2, It is very likely that the memset function call will be removed.

I believe this is due to an optimization technique called dead code removal. If a compiler sees that the char array is not going to be used in following code (like to be written in, be printed to the screen, or be sent via socket), it feels that the memset function call is unnecessary, thus making removes it from the compiled object file. If the vector array is reused for other purposes, and the compiler again can prove that its content is overwritten, the compiler might also conclude that the memset is unnecessary, for if the content of the array will be overwritten anyway, whey bother firstly zeroing all its elements, thus again optimize away the memset.

Problem is, this optimization is sometimes not what a programmer would expect. For example, if the memset function is called in a security sensitive context to zeroize sensitive information like user passwords, it is undesirable for it to be optimized away.

To force memset actually to be executed, we can define the following memset replacement:

    void memset_s(volatile char * p, int value, size_t num){
    	int i;
    	for(i=0; i<num; ++i)
    		{*(p+i)=value;
    	}
    }

Because the function memset_s takes a pointer to volatile char as its first parameter, writing to the pointed char cannot be optimized away.

Actually, C11 introduced a function memset_s with the signature

     errno_t memset_s( void *dest, rsize_t destsz, int ch, rsize_t count );

The C11 standard mandates that this function won’t be optimized away by the compiler.