From eb0c6e0dd9230d1176f1e92a9101b53823349d4c Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 24 Mar 2024 15:54:04 +0300 Subject: [PATCH] C: add mem/safe_mem.* --- c-programming/mem/safe_mem.h | 65 +++++++++++++++++++++++++++++++ c-programming/mem/safe_mem.test.c | 63 ++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 c-programming/mem/safe_mem.h create mode 100644 c-programming/mem/safe_mem.test.c diff --git a/c-programming/mem/safe_mem.h b/c-programming/mem/safe_mem.h new file mode 100644 index 0000000..c6257fe --- /dev/null +++ b/c-programming/mem/safe_mem.h @@ -0,0 +1,65 @@ +/* + * safe_mem.h + * + * A header-only library (macro collection) for safer memory management. + * + * Author: Intel A80486DX2-66 + * License: Creative Commons Zero 1.0 Universal + */ + +#ifndef _SAFE_MEM_H +#define _SAFE_MEM_H + +#include + +#define SAFE_FREE_ERROR_HOOK /* user-defined */ + +#define safe_free(ptr) do { \ + /* prevents NULL-freeing and double freeing */ \ + if (ptr != NULL) { \ + free(ptr); \ + ptr = NULL; \ + } else { SAFE_FREE_ERROR_HOOK; } \ +} while (0) + +#define precise_malloc(nmemb, size) \ + /* prevents incorrect casting */ \ + malloc((size_t) nmemb * (size_t) size) + +/* secure_erase(dest, count): erases memory explicitly */ +#if defined(__FreeBSD__) +# define NO_SECURE_ERASE_WARRANTY 0 +# define SECURE_ERASE_WARRANTY "OpenBSD/FreeBSD: explicit_bzero" + +# include +# define secure_erase explicit_bzero +#elif defined(_WIN32) +# define NO_SECURE_ERASE_WARRANTY 0 +# define SECURE_ERASE_WARRANTY "Microsoft Windows: SecureZeroMemory" + +# include +# define secure_erase SecureZeroMemory +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# define NO_SECURE_ERASE_WARRANTY 0 +# define SECURE_ERASE_WARRANTY "C11+: memset_s" + +# define secure_erase(dest, count) memset_s(dest, count, 0, count) +#else +# define NO_SECURE_ERASE_WARRANTY 1 + +# define __observe__(ptr) do { \ + if (*ptr == 0) { \ + ++(*ptr); \ + fprintf(stderr, ""); \ + } else \ + --(*ptr); \ +} while (0) + +# define secure_erase(dest, count) do { \ + memset(dest, 0, count); \ + for (size_t i = 0; i < count; i++) \ + __observe__(dest[i]); \ +} while (0) +#endif + +#endif /* _SAFE_MEM_H */ diff --git a/c-programming/mem/safe_mem.test.c b/c-programming/mem/safe_mem.test.c new file mode 100644 index 0000000..118c6d0 --- /dev/null +++ b/c-programming/mem/safe_mem.test.c @@ -0,0 +1,63 @@ +/* + * safe_mem.c + * + * Author: Intel A80486DX2-66 + * License: Creative Commons Zero 1.0 Universal + */ + +#include +#include + +#include "safe_mem.h" + +#undef SAFE_FREE_ERROR_HOOK +#define SAFE_FREE_ERROR_HOOK do { \ + fprintf(stderr, "Double freeing detected!\n"); \ + exit(EXIT_FAILURE); \ +} while (0) + +#define PRINT_POINTER(caption, ptr) \ + printf(caption " = %p\n", (void*) ptr); +#define DUMP_INT_ARRAY(caption, ptr, count) do { \ + printf("%s: [", caption); \ + for (size_t i = 0; i < count; i++) { \ + printf("%d", ptr[i]); \ + if (i != (count - 1)) \ + printf(", "); \ + } \ + printf("]\n"); \ +} while (0) + +int main(void) { +#define COUNT 4 + int* integers = precise_malloc(COUNT, sizeof(int)); + PRINT_POINTER("int* integers (before freeing)", integers); + + integers[0] = 0; + integers[1] = EOF; + integers[2] = STDERR_FILENO; + integers[3] = 1; + DUMP_INT_ARRAY("int* integers (before secure erasure)", integers, COUNT); + printf("Secure erasure is " +#if NO_SECURE_ERASE_WARRANTY + "not guaranteed!" +#else + "guaranteed: %s" +#endif + "\n" +#if !NO_SECURE_ERASE_WARRANTY + , SECURE_ERASE_WARRANTY +#endif + ); + + secure_erase(integers, COUNT * sizeof(int)); + DUMP_INT_ARRAY("int* integers (after secure erasure)", integers, COUNT); + + safe_free(integers); + PRINT_POINTER("int* integers (after freeing)", integers); + fflush(stdout); + safe_free(integers); + PRINT_POINTER("int* integers (after two free() calls)", integers); + + return EXIT_SUCCESS; +}