summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c
new file mode 100644
index 0000000..d6151ec
--- /dev/null
+++ b/src/alloc.c
@@ -0,0 +1,63 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include "byte.h"
+#include "alloc.h"
+
+#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
+#define SPACE 4096 /* must be multiple of ALIGNMENT */
+#define space ((char *)realspace)
+
+/**
+ * @file alloc.c
+ * @authors djb, feh, jmh
+ * @ref qmail
+ * @brief Generic allocation of heap memory
+ */
+
+typedef union {
+ char irrelevant[ALIGNMENT];
+ double d;
+} aligned;
+
+static aligned realspace[SPACE / ALIGNMENT];
+static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
+
+// /*@null@*//*@out@*/char *alloc(unsigned int n) -- old style
+void *alloc(unsigned int n)
+{
+ char *x;
+
+/* Guninski exploit + patch from Qualys (CVE-2005-1513) */
+
+ if (n >= (INT_MAX >> 3)) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
+ if (n <= avail) { avail -= n; return space + avail; }
+ x = malloc(n);
+ if (!x) errno = ENOMEM;
+ return x;
+}
+
+void alloc_free(void *x)
+{
+ if (x >= space)
+ if (x < space + SPACE)
+ return; /* XXX: assuming that pointers are flat */
+ free(x);
+}
+
+int alloc_re(void **x,unsigned int m,unsigned int n)
+{
+ char *y;
+
+ y = alloc(n);
+ if (!y) return 0;
+ byte_copy(y,m,*x);
+ qfree(*x);
+ *x = y;
+ return 1;
+}