diff options
author | Olly Betts <olly@survex.com> | 2022-03-06 15:36:42 +1300 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2022-03-06 15:36:42 +1300 |
commit | 747a51f09518eede4b2c6f5e9af8f95865fa4d7d (patch) | |
tree | dfe6bfd3f63bfa89f1543a8f3fc6c2cc65054181 | |
parent | 6d29260a1a41deb4f9db38401e9f37000573d9ad (diff) | |
download | swig-747a51f09518eede4b2c6f5e9af8f95865fa4d7d.tar.gz |
Try to prevent direct use of exit(), malloc(), etc
Use `#pragma GCC poison` (supported since GCC 3, maybe earlier) when
compiling with GCC to help prevent direct uses being introduced for
functions which DOH provides a wrapper for.
-rw-r--r-- | Source/CParse/parser.y | 12 | ||||
-rw-r--r-- | Source/DOH/doh.h | 43 | ||||
-rw-r--r-- | Source/DOH/memory.c | 9 | ||||
-rw-r--r-- | Source/Modules/main.cxx | 2 |
4 files changed, 50 insertions, 16 deletions
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 3ca06e6b0..7a5ef42c5 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -25,6 +25,15 @@ %{ #define yylex yylex +/* doh.h uses #pragma GCC posion with GCC to prevent direct calls to certain + * standard C library functions being introduced, but those cause errors due + * to checks like `#if defined YYMALLOC || defined malloc` in the bison + * template code. We can't easily arrange to include headers after that + * template code, so instead we disable the problematic poisoning for this + * file. + */ +#define DOH_NO_POISON_MALLOC_FREE + #include "swig.h" #include "cparse.h" #include "preprocessor.h" @@ -34,6 +43,9 @@ #undef alloca #define alloca Malloc +#define YYMALLOC Malloc +#define YYFREE Free + /* ----------------------------------------------------------------------------- * Externals * ----------------------------------------------------------------------------- */ diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index 273966d19..216ed0594 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -18,8 +18,9 @@ #include "swigconfig.h" #endif -#include <stdio.h> #include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> /* Set the namespace prefix for DOH API functions. This can be used to control visibility of the functions in libraries */ @@ -278,18 +279,18 @@ extern int DohGetmark(DOH *obj); /* Set the function for DohExit() to call instead of exit(). * - * The registered function can perform clean up, etc and then should call - * exit(status) to end the process. Bear in mind that this can be called - * after malloc() has failed, so avoiding allocating additional memory in - * the registered function is a good idea. + * The registered function can perform clean up, etc. It should simply + * return when done and then exit() will get called. Bear in mind that + * the handler function can be called after malloc() has failed, so it's + * a good idea for it to avoid allocating additional memory. * - * The registered function is unregistered by DohExit() before calling it to - * avoid the potential for infinite loops. + * The registered handler function is unregistered by DohExit() before calling + * it to avoid the potential for infinite loops. * * Note: This is sort of like C's atexit(), only for DohExit(). However * only one function can be registered (setting a new function overrides the - * previous one) and the registered function is passed the exit status and - * should itself call exit(). + * previous one) and the registered function is passed the exit status so can + * vary its actions based on that. */ extern void DohSetExitHandler(void (*new_handler)(int)); extern void DohExit(int status); @@ -477,5 +478,29 @@ extern void DohMemoryDebug(void); #define NIL (char *) NULL +/* Defines to allow use of poisoned identifiers. + * + * For DOH-internal use only! + */ +#define doh_internal_calloc calloc +#define doh_internal_exit exit +/* doh_internal_free not needed as Free() is a macro defined above. */ +#define doh_internal_malloc malloc +#define doh_internal_realloc realloc + +#ifdef __GNUC__ +/* Use Malloc(), Realloc(), Calloc(), and Free() instead (which will exit with + * an error rather than return NULL). + */ +# ifndef DOH_NO_POISON_MALLOC_FREE +/* This works around bison's template checking if malloc and free are defined, + * which triggers GCC's poison checks. + */ +# pragma GCC poison malloc free +# pragma GCC poison realloc calloc +# endif +/* Use Exit() instead (which will remove output files on error). */ +# pragma GCC poison abort exit +#endif #endif /* DOH_H */ diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c index dcba95b56..88ed0f959 100644 --- a/Source/DOH/memory.c +++ b/Source/DOH/memory.c @@ -250,9 +250,8 @@ void DohExit(int status) { */ doh_exit_handler = NULL; handler(status); - } else { - exit(status); } + doh_internal_exit(status); } static void allocation_failed(size_t n, size_t size) { @@ -275,19 +274,19 @@ static void allocation_failed(size_t n, size_t size) { } void *DohMalloc(size_t size) { - void *p = malloc(size); + void *p = doh_internal_malloc(size); if (!p) allocation_failed(1, size); return p; } void *DohRealloc(void *ptr, size_t size) { - void *p = realloc(ptr, size); + void *p = doh_internal_realloc(ptr, size); if (!p) allocation_failed(1, size); return p; } void *DohCalloc(size_t n, size_t size) { - void *p = calloc(n, size); + void *p = doh_internal_calloc(n, size); if (!p) allocation_failed(n, size); return p; } diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index a6a04eb5d..239deabeb 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -1417,6 +1417,4 @@ static void SWIG_exit_handler(int status) { } } } - - exit(status); } |