libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

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:
MMakefile | 2+-
DTODO | 1-
Mman/libzahl.7 | 6++++++
Asrc/allocator.c | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/internals.h | 17+++++------------
Msrc/zfree.c | 28+++++++++++++++++++++++++++-
Msrc/zsetup.c | 8++++++++
Msrc/zunsetup.c | 12+++++++++---
Mzahl.h | 1+
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>