summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlly Betts <olly@survex.com>2022-03-06 15:36:42 +1300
committerOlly Betts <olly@survex.com>2022-03-06 15:36:42 +1300
commit747a51f09518eede4b2c6f5e9af8f95865fa4d7d (patch)
treedfe6bfd3f63bfa89f1543a8f3fc6c2cc65054181
parent6d29260a1a41deb4f9db38401e9f37000573d9ad (diff)
downloadswig-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.y12
-rw-r--r--Source/DOH/doh.h43
-rw-r--r--Source/DOH/memory.c9
-rw-r--r--Source/Modules/main.cxx2
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);
}