diff options
Diffstat (limited to 'missing/explicit_bzero.c')
| -rw-r--r-- | missing/explicit_bzero.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/missing/explicit_bzero.c b/missing/explicit_bzero.c new file mode 100644 index 0000000000..59417e158e --- /dev/null +++ b/missing/explicit_bzero.c @@ -0,0 +1,91 @@ +#ifndef __STDC_WANT_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s() */ +#endif + +#include "ruby/missing.h" +#include <string.h> + +#ifdef _WIN32 +#include <windows.h> +#endif + +/* Similar to bzero(), but has a guarantee not to be eliminated from compiler + optimization. */ + +/* OS support note: + * BSDs have explicit_bzero(). + * macOS has memset_s(). + * Windows has SecureZeroMemory() since XP. + * Linux has explicit_bzero() since glibc 2.25, musl libc 1.1.20. + */ + +/* + * Following URL explains why memset_s is added to the standard. + * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf + */ + +#ifndef FUNC_UNOPTIMIZED +# define FUNC_UNOPTIMIZED(x) x +#endif + +#undef explicit_bzero +#ifndef HAVE_EXPLICIT_BZERO + #ifdef HAVE_EXPLICIT_MEMSET +void +explicit_bzero(void *b, size_t len) +{ + (void)explicit_memset(b, 0, len); +} + #elif defined HAVE_MEMSET_S +void +explicit_bzero(void *b, size_t len) +{ + memset_s(b, len, 0, len); +} + #elif defined SecureZeroMemory +void +explicit_bzero(void *b, size_t len) +{ + SecureZeroMemory(b, len); +} + + #elif defined HAVE_FUNC_WEAK + +/* A weak function never be optimized away. Even if nobody uses it. */ +WEAK(void ruby_explicit_bzero_hook_unused(void *buf, size_t len)); +void +ruby_explicit_bzero_hook_unused(void *buf, size_t len) +{ +} + +void +explicit_bzero(void *b, size_t len) +{ + memset(b, 0, len); + ruby_explicit_bzero_hook_unused(b, len); +} + + #else /* Your OS have no capability. Sigh. */ + +FUNC_UNOPTIMIZED(void explicit_bzero(void *b, size_t len)); +#undef explicit_bzero + +void +explicit_bzero(void *b, size_t len) +{ + /* + * volatile is not enough if the compiler has an LTO (link time + * optimization). At least, the standard provides no guarantee. + * However, gcc and major other compilers never optimize a volatile + * variable away. So, using volatile is practically ok. + */ + volatile char* p = (volatile char*)b; + + while(len) { + *p = 0; + p++; + len--; + } +} + #endif +#endif /* HAVE_EXPLICIT_BZERO */ |
