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.
This commit is contained in:
Olly Betts 2022-03-06 15:36:42 +13:00
commit 747a51f095
4 changed files with 50 additions and 16 deletions

View file

@ -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
* ----------------------------------------------------------------------------- */

View file

@ -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 */

View file

@ -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;
}

View file

@ -1417,6 +1417,4 @@ static void SWIG_exit_handler(int status) {
}
}
}
exit(status);
}