commit c1f4d263ec1004512cdd6b38b351eb2fe2321c22
Author:     Mattias Andrée <[email protected]>
AuthorDate: Sat Mar 5 22:27:04 2016 +0100
Commit:     Mattias Andrée <[email protected]>
CommitDate: Sat Mar 5 22:28:33 2016 +0100

    Add memory pool, also let the user know that libzahl is not designed for 
cryptography
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/Makefile b/Makefile
index d9ecce5..691e35f 100644
--- 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
deleted file mode 100644
index 94dc424..0000000
--- a/TODO
+++ /dev/null
@@ -1 +0,0 @@
-Allocations shall be cached.
diff --git a/man/libzahl.7 b/man/libzahl.7
index d7a9728..6f7aa59 100644
--- 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
new file mode 100644
index 0000000..46cca89
--- /dev/null
+++ 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
index 5c0ac32..8a9c379 100644
--- 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
index 95eb084..2a1680a 100644
--- 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
index 8b5221d..151f2f6 100644
--- 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
index 184f96f..9926354 100644
--- 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
index 39d08a2..4cb1373 100644
--- 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>

Reply via email to