commit c1f4d263ec1004512cdd6b38b351eb2fe2321c22
parent 48a89e0e110907a7a60ed8f5a0977e3b34661259
Author: Mattias Andrée <maandree@kth.se>
Date: Sat, 5 Mar 2016 22:27:04 +0100
Add memory pool, also let the user know that libzahl is not designed for cryptography
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
9 files changed, 98 insertions(+), 18 deletions(-)
diff --git a/Makefile b/Makefile
@@ -63,7 +63,7 @@ INLINE_FUN =\
zzero\
zsignum
-OBJ = $(FUN:=.o)
+OBJ = $(FUN:=.o) allocator.o
MAN = $(foreach F,$(FUN) $(INLINE_FUN),man/$(F).3) man/libzahl.7
all: libzahl.a
diff --git a/TODO b/TODO
@@ -1 +0,0 @@
-Allocations shall be cached.
diff --git a/man/libzahl.7 b/man/libzahl.7
@@ -33,5 +33,11 @@ I think it can be done better.
.SH NOTES
.B libzahl
is currently not thread-safe.
+.P
+You are strongly discouraged from using
+.B libzahl
+for cryptographic applications. Instead, use a library
+specifically targeting cryptography, otherwise, your
+program may be subject to side-channel attacks.
.SH SEE ALSO
.BR zsetup (3)
diff --git a/src/allocator.c b/src/allocator.c
@@ -0,0 +1,41 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals.h"
+
+#include <stdint.h>
+
+
+void
+libzahl_realloc(z_t a, size_t need)
+{
+ size_t i, x;
+ zahl_char_t *new;
+
+ /* Find n such that n is a minimal power of 2 ≥ need. */
+ if ((need & (~need + 1)) != need) {
+ need |= need >> 1;
+ need |= need >> 2;
+ need |= need >> 4;
+ for (i = sizeof(need), x = 8; i; i >>= 1, x <<= 1)
+ need |= need >> x;
+ need += 1;
+ }
+
+ for (i = 0, x = need; x; x >>= 1)
+ i += 1;
+
+ if (libzahl_pool_n[i]) {
+ libzahl_pool_n[i]--;
+ new = libzahl_pool[i][libzahl_pool_n[i]];
+ zmemcpy(new, a->chars, a->alloced);
+ zfree(a);
+ a->chars = new;
+ } else {
+ a->chars = realloc(a->chars, need * sizeof(zahl_char_t));
+ if (!a->chars) {
+ if (!errno) /* sigh... */
+ errno = ENOMEM;
+ FAILURE(errno);
+ }
+ }
+ a->alloced = need;
+}
diff --git a/src/internals.h b/src/internals.h
@@ -56,6 +56,9 @@ extern z_t libzahl_tmp_divmod_ds[BITS_PER_CHAR];
extern jmp_buf libzahl_jmp_buf;
extern int libzahl_set_up;
extern int libzahl_error;
+extern zahl_char_t **libzahl_pool[sizeof(size_t) * 8];
+extern size_t libzahl_pool_n[sizeof(size_t) * 8];
+extern size_t libzahl_pool_alloc[sizeof(size_t) * 8];
#define FAILURE(error) (libzahl_error = (error), longjmp(libzahl_jmp_buf, 1))
#define zmemcpy(d, s, n) memcpy(d, s, (n) * sizeof(zahl_char_t))
@@ -65,19 +68,9 @@ extern int libzahl_error;
#define SET_SIGNUM(a, signum) ((a)->sign = (signum))
#define SET(a, b) do { if ((a) != (b)) zset(a, b); } while (0)
-#define ENSURE_SIZE(a, n) do { if ((a)->alloced < (n)) zahl_realloc(a, (n)); } while (0)
+#define ENSURE_SIZE(a, n) do { if ((a)->alloced < (n)) libzahl_realloc(a, (n)); } while (0)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-static inline void
-zahl_realloc(z_t p, size_t n)
-{
- p->chars = realloc(p->chars, n * sizeof(zahl_char_t));
- if (!p->chars) {
- if (!errno) /* sigh... */
- errno = ENOMEM;
- FAILURE(errno);
- }
- p->alloced = n;
-}
+void libzahl_realloc(z_t a, size_t need);
diff --git a/src/zfree.c b/src/zfree.c
@@ -5,5 +5,31 @@
void
zfree(z_t a)
{
- free(a->chars);
+ size_t i = 0, x, j;
+ zahl_char_t **new;
+
+ if (!a->chars)
+ return;
+
+ for (x = a->alloced; x; x >>= 1)
+ i += 1;
+
+ j = libzahl_pool_n[i]++;
+
+ if (j == libzahl_pool_alloc[i]) {
+ x = j ? ((j * 3) >> 1) : 128;
+ new = realloc(libzahl_pool[i], x * sizeof(zahl_char_t *));
+ if (!new) {
+ free(a->chars);
+ free(libzahl_pool[i]);
+ libzahl_pool_n[i] = 0;
+ libzahl_pool[i] = 0;
+ libzahl_pool_alloc[i] = 0;
+ return;
+ }
+ libzahl_pool[i] = new;
+ libzahl_pool_alloc[i] = x;
+ }
+
+ libzahl_pool[i][j] = a->chars;
}
diff --git a/src/zsetup.c b/src/zsetup.c
@@ -12,6 +12,9 @@ z_t libzahl_tmp_divmod_ds[BITS_PER_CHAR];
jmp_buf libzahl_jmp_buf;
int libzahl_set_up = 0;
int libzahl_error;
+zahl_char_t **libzahl_pool[sizeof(size_t) * 8];
+size_t libzahl_pool_n[sizeof(size_t) * 8];
+size_t libzahl_pool_alloc[sizeof(size_t) * 8];
void
@@ -22,6 +25,11 @@ zsetup(jmp_buf env)
if (!libzahl_set_up) {
libzahl_set_up = 1;
+
+ memset(libzahl_pool, 0, sizeof(libzahl_pool));
+ memset(libzahl_pool_n, 0, sizeof(libzahl_pool_n));
+ memset(libzahl_pool_alloc, 0, sizeof(libzahl_pool_alloc));
+
#define X(x)\
zinit(x);
LIST_TEMPS;
diff --git a/src/zunsetup.c b/src/zunsetup.c
@@ -9,14 +9,20 @@ zunsetup(void)
if (libzahl_set_up) {
libzahl_set_up = 0;
#define X(x)\
- zfree(x);
+ free(x->chars);
LIST_TEMPS;
#undef X
#define X(x, f, v)\
- zfree(x);
+ free(x->chars);
LIST_CONSTS;
#undef X
for (i = BITS_PER_CHAR; i--;)
- zfree(libzahl_tmp_divmod_ds[i]);
+ free(libzahl_tmp_divmod_ds[i]->chars);
+
+ for (i = sizeof(libzahl_pool) / sizeof(*libzahl_pool); i--;) {
+ while (libzahl_pool_n[i]--)
+ free(libzahl_pool[i][libzahl_pool_n[i]]);
+ free(libzahl_pool[i]);
+ }
}
}
diff --git a/zahl.h b/zahl.h
@@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */
/* Warning: libzahl is not thread-safe. */
+/* Caution: Do not use libzahl for cryptographic applications, use a specialised library. */
#include <stddef.h>