651 | 651 |
*/
|
652 | 652 |
#ifdef _WIN32
|
653 | 653 |
# define zap(ptr, len) SecureZeroMemory(ptr, len)
|
654 | |
#elif defined(__GNUC__)
|
|
654 |
#elif defined(__STDC_LIB_EXT1__)
|
|
655 |
/*
|
|
656 |
* Use memset_s() which cannot be optimized out. Avoid memset_s(NULL, 0, 0, 0)
|
|
657 |
* which would cause a runtime constraint violation.
|
|
658 |
*/
|
655 | 659 |
static inline void zap(void *ptr, size_t len)
|
656 | 660 |
{
|
657 | |
memset(ptr, 0, len);
|
658 | |
/*
|
659 | |
* Some versions of gcc have gotten clever enough to eliminate a
|
660 | |
* memset call right before the block in question is released.
|
661 | |
* This (empty) asm requires it to assume that we're doing
|
662 | |
* something interesting with the stored (zero) value, so the
|
663 | |
* memset can't be eliminated.
|
664 | |
*
|
665 | |
* An optimizer that looks at assembly or object code may not be
|
666 | |
* fooled, and may still cause the memset to go away. Address
|
667 | |
* that problem if and when we encounter it.
|
668 | |
*
|
669 | |
* This also may not be enough if free() does something
|
670 | |
* interesting like purge memory locations from a write-back cache
|
671 | |
* that hasn't written back the zero bytes yet. A memory barrier
|
672 | |
* instruction would help in that case.
|
673 | |
*/
|
674 | |
asm volatile ("" : : "g" (ptr), "g" (len));
|
|
661 |
if (len > 0)
|
|
662 |
memset_s(ptr, len, 0, len);
|
|
663 |
}
|
|
664 |
#elif defined(__GNUC__) || defined(__clang__)
|
|
665 |
/*
|
|
666 |
* Use an asm statement which declares a memory clobber to force the memset to
|
|
667 |
* be carried out. Avoid memset(NULL, 0, 0) which has undefined behavior.
|
|
668 |
*/
|
|
669 |
static inline void zap(void *ptr, size_t len)
|
|
670 |
{
|
|
671 |
if (len > 0)
|
|
672 |
memset(ptr, 0, len);
|
|
673 |
__asm__ __volatile__("" : : "r" (ptr) : "memory");
|
675 | 674 |
}
|
676 | 675 |
#else
|
677 | |
/* Use a function from libkrb5support to defeat inlining. */
|
|
676 |
/*
|
|
677 |
* Use a function from libkrb5support to defeat inlining unless link-time
|
|
678 |
* optimization is used. The function uses a volatile pointer, which prevents
|
|
679 |
* current compilers from optimizing out the memset.
|
|
680 |
*/
|
678 | 681 |
# define zap(ptr, len) krb5int_zap(ptr, len)
|
679 | 682 |
#endif
|
680 | 683 |
|