aboutsummaryrefslogtreecommitdiff
path: root/lib/alloc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/alloc')
-rw-r--r--lib/alloc/bufalloc.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/lib/alloc/bufalloc.c b/lib/alloc/bufalloc.c
new file mode 100644
index 0000000..a81f5b9
--- /dev/null
+++ b/lib/alloc/bufalloc.c
@@ -0,0 +1,29 @@
+#include <errno.h>
+#if __has_include(<stdckdint.h>)
+# include <stdckdint.h>
+# warning "stdckdint.h now available; remove manual ckd_*() implementations"
+#elifdef __GNUC__
+# define ckd_add(r, a, b) ((bool)__builtin_add_overflow(a, b, r))
+# define ckd_mul(r, a, b) ((bool)__builtin_mul_overflow(a, b, r))
+#else
+# define ckd_add(r, a, b) (*(r) = (a) + (b))
+# define ckd_mul(r, a, b) (*(r) = (a) * (b))
+# warning "ckd_*() not supported on the current platform"
+#endif
+#include <stdlib.h>
+
+#include "alloc.h"
+#include "errors.h"
+
+void *
+bufalloc(void *p, size_t n, size_t m)
+{
+ if (ckd_mul(&n, n, m)) {
+ errno = EOVERFLOW;
+ err(__func__);
+ }
+
+ if (!(p = realloc(p, n)))
+ err(__func__);
+ return p;
+}