diff options
Diffstat (limited to 'libmu_sieve/mem.c')
-rw-r--r-- | libmu_sieve/mem.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c index f03b06dd5..25dc26c5b 100644 --- a/libmu_sieve/mem.c +++ b/libmu_sieve/mem.c @@ -196,11 +196,42 @@ mu_sieve_reclaim_value (void *p) /* For now, the same as _default. Will change in the future */ free (p); } - + +/* Based on gnulib's x2nrealloc */ void -mu_sieve_reclaim_tag (void *p) +mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb, + size_t size) { - mu_sieve_runtime_tag_t *tag = p; - mu_sieve_reclaim_value (tag->arg); -} + void *ptr = *pptr; + size_t nmemb = *pnmemb; + + if (!ptr) + { + if (!nmemb) + { + /* Initial allocation size */ + nmemb = 16; + } + } + else + { + /* Set NMEMB = floor (1.5 * NMEMB) + 1 so that progress is made even + if NMEMB == 0. + Check for overflow, so that NMEMB * SIZE stays in size_t range. + The check may be slightly conservative, but an exact check isn't + worth the trouble. */ + if ((size_t) -1 / 3 * 2 / size <= nmemb) + { + mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, + _("requested too much memory %zu * %zu"), + nmemb, size); + mu_sieve_abort (mach); + } + nmemb += nmemb / 2 + 1; + } + ptr = mu_sieve_realloc (mach, ptr, nmemb * size); + + *pptr = ptr; + *pnmemb = nmemb; +} |