The wipememory macro relies upon the volatile qualifier, which appears to be an
abuse of the use of the qualifier.
According to Ian Lance Taylor, GCC interprets the qualifier to mean memory that
can be changed by hardware (memory mapped hardware). GCC's interpretation is a
different interpretation than Microsoft, et al. See
https://gcc.gnu.org/ml/gcc-help/2012-03/msg00242.html for Taylor's comments.
Unfortunately, memset_s is not available on GNU systems, so its not an
alternative. Its unfortunate because its guaranteed to *not* be removed by the C
standard. Also see "[Bug libc/17879] Library is missing memset_s",
https://sourceware.org/bugzilla/show_bug.cgi?id=17879.
$ grep -R wipememory * | grep define
libgcrypt-1.6.3/src/g10lib.h:#define wipememory2(_ptr,_set,_len) do { \
libgcrypt-1.6.3/src/g10lib.h:#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
...
#define wipememory2(_ptr,_set,_len) do { \
volatile char *_vptr=(volatile char *)(_ptr); \ size_t _vlen=(_len); \ unsigned char _vset=(_set); \ fast_wipememory2(_vptr,_vset,_vlen); \ while(_vlen) { *_vptr=(_vset); _vptr++; _vlen--; } \ } while(0)
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
On Win32 systems under MinGW/Cygwin, it might be advisable to call
SecureZeroMemory if available. Its also guaranteed to *not* be removed, and its
available on Windows 2000 and higher. Also see "SecureZeroMemory function",
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366877%28v=vs.85%29.aspx.
The best alternative I've been able to find for GCC and Intel x86's is the
following. Ironically, __asm__ __volatile__ is guaranteed to not be removed, too.
string s("Hello world"); cout << "S: " << s << endl; char* ptr = &s[0]; size_t size = s.length(); if(ptr && size) { /* Needed because we can't just say to GCC, */ /* "give me a register that you choose". */ void* dummy; __asm__ __volatile__ ( "%=:\n\t" /* generate a unique label for TOP */
#if (__WORDSIZE == 64)
"subq $1, %2\n\t" /* 0-based index */
#elif (__WORDSIZE == 32)
"subl $1, %2\n\t" /* 0-based index */
#elif (__WORDSIZE == 16)
"subw $1, %2\n\t" /* 0-based index */
#else
error Unknown machine word size
#endif
"lea (%1, %2), %0\n\t" /* calcualte ptr[idx] */ "movb $0, (%0)\n\t" /* 0 -> ptr[size - 1] .. ptr[0] */ "jnz %=b\n\t" /* Back to TOP if non-zero */ : "=&r" (dummy) : "r" (ptr), "r" (size) : "0", "1", "2", "cc" ); }