summaryrefslogtreecommitdiff
path: root/mini-gmp
diff options
context:
space:
mode:
authorNiels M?ller <nisse@lysator.liu.se>2020-05-27 20:45:14 +0200
committerNiels M?ller <nisse@lysator.liu.se>2020-05-27 20:45:14 +0200
commit4bfa582d63c07f6c82ea5026b47d5421c8788417 (patch)
treebabdc0578b5c34ee6b79c24f08cc1d8e0b9d0fba /mini-gmp
parent4604cb0c838d4bd9ad1616b8531f2defbb0671a9 (diff)
downloadgmp-4bfa582d63c07f6c82ea5026b47d5421c8788417.tar.gz
mini-gmp: Pass correct old_size to custom free and reallocate functions.
Contributed by Minux Ma.
Diffstat (limited to 'mini-gmp')
-rw-r--r--mini-gmp/ChangeLog20
-rw-r--r--mini-gmp/README7
-rw-r--r--mini-gmp/mini-gmp.c102
-rw-r--r--mini-gmp/mini-mpq.c16
-rw-r--r--mini-gmp/tests/t-double.c2
-rw-r--r--mini-gmp/tests/t-mpq_str.c7
-rw-r--r--mini-gmp/tests/t-str.c5
-rw-r--r--mini-gmp/tests/testutils.c27
-rw-r--r--mini-gmp/tests/testutils.h2
9 files changed, 119 insertions, 69 deletions
diff --git a/mini-gmp/ChangeLog b/mini-gmp/ChangeLog
index 8c235133d..826ce10c3 100644
--- a/mini-gmp/ChangeLog
+++ b/mini-gmp/ChangeLog
@@ -1,3 +1,23 @@
+2020-05-27 Minux Ma <minux.ma@gmail.com>
+
+ Pass correct old_size to custom free and reallocate functions.
+ * mini-gmp.c (gmp_alloc): Renamed macro from...
+ (gmp_xalloc): .. old name.
+ (gmp_realloc): New macro, with old_size argument.
+ (gmp_free): Take size argument, and pass on.
+ (gmp_realloc_limbs): Add old_size argument, and rename from
+ (gmp_xrealloc_limbs): ... old name..
+ (gmp_free_limbs): New function, with size argument. Lots of
+ updates, only non-trivial ones listed below.
+ (mpn_div_qr_1_preinv): Use gmp_free_limbs, simplify dealloc logic.
+ (mpz_get_str): Realloc result area when needed, to match final
+ digit count.
+ * mini-mpq.c (mpq_get_str, mpq_out_str, mpq_set_str): Pass correct
+ size to gmp_free_func.
+ * tests/testutils.c (tu_realloc, tu_free): Check that old_size
+ matches size in block header.
+ (testfree): Add size argument. Update all callers.
+
2020-04-20 Niels Möller <nisse@lysator.liu.se>
* mini-gmp.c (mpz_fits_slong_p): Simplify, by using mpz_cmp_si.
diff --git a/mini-gmp/README b/mini-gmp/README
index b02b8da71..fd54054c7 100644
--- a/mini-gmp/README
+++ b/mini-gmp/README
@@ -45,13 +45,6 @@ as specified in the GMP manual, with a few exceptions:
mpz_export and mpz_import support only NAILS = 0.
- The REALLOC_FUNC and FREE_FUNC registered with
- mp_set_memory_functions does not get the correct size of the
- allocated block in the corresponding argument. mini-gmp always
- passes zero for these rarely used arguments.
-
- When mpz_get_str allocates the block, it can be longer than needed.
-
The performance target for mini-gmp is to be at most 10 times slower
than the real GMP library, for numbers of size up to a few hundred
bits. No asymptotically fast algorithms are included in mini-gmp, so
diff --git a/mini-gmp/mini-gmp.c b/mini-gmp/mini-gmp.c
index e20b94ab7..a7b719098 100644
--- a/mini-gmp/mini-gmp.c
+++ b/mini-gmp/mini-gmp.c
@@ -351,20 +351,27 @@ mp_set_memory_functions (void *(*alloc_func) (size_t),
gmp_free_func = free_func;
}
-#define gmp_xalloc(size) ((*gmp_allocate_func)((size)))
-#define gmp_free(p) ((*gmp_free_func) ((p), 0))
+#define gmp_alloc(size) ((*gmp_allocate_func)((size)))
+#define gmp_free(p, size) ((*gmp_free_func) ((p), (size)))
+#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size))
static mp_ptr
-gmp_xalloc_limbs (mp_size_t size)
+gmp_alloc_limbs (mp_size_t size)
{
- return (mp_ptr) gmp_xalloc (size * sizeof (mp_limb_t));
+ return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t));
}
static mp_ptr
-gmp_xrealloc_limbs (mp_ptr old, mp_size_t size)
+gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size)
{
assert (size > 0);
- return (mp_ptr) (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t));
+ return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t));
+}
+
+static void
+gmp_free_limbs (mp_ptr old, mp_size_t size)
+{
+ gmp_free (old, size * sizeof (mp_limb_t));
}
@@ -956,11 +963,17 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
mp_limb_t d, di;
mp_limb_t r;
mp_ptr tp = NULL;
+ mp_size_t tn = 0;
if (inv->shift > 0)
{
/* Shift, reusing qp area if possible. In-place shift if qp == np. */
- tp = qp ? qp : gmp_xalloc_limbs (nn);
+ tp = qp;
+ if (!tp)
+ {
+ tn = nn;
+ tp = gmp_alloc_limbs (tn);
+ }
r = mpn_lshift (tp, np, nn, inv->shift);
np = tp;
}
@@ -977,8 +990,8 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
if (qp)
qp[nn] = q;
}
- if ((inv->shift > 0) && (tp != qp))
- gmp_free (tp);
+ if (tn)
+ gmp_free_limbs (tp, tn);
return r >> inv->shift;
}
@@ -1136,13 +1149,13 @@ mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
mpn_div_qr_invert (&inv, dp, dn);
if (dn > 2 && inv.shift > 0)
{
- tp = gmp_xalloc_limbs (dn);
+ tp = gmp_alloc_limbs (dn);
gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift));
dp = tp;
}
mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv);
if (tp)
- gmp_free (tp);
+ gmp_free_limbs (tp, dn);
}
@@ -1428,14 +1441,14 @@ mpz_init2 (mpz_t r, mp_bitcnt_t bits)
r->_mp_alloc = rn;
r->_mp_size = 0;
- r->_mp_d = gmp_xalloc_limbs (rn);
+ r->_mp_d = gmp_alloc_limbs (rn);
}
void
mpz_clear (mpz_t r)
{
if (r->_mp_alloc)
- gmp_free (r->_mp_d);
+ gmp_free_limbs (r->_mp_d, r->_mp_alloc);
}
static mp_ptr
@@ -1444,9 +1457,9 @@ mpz_realloc (mpz_t r, mp_size_t size)
size = GMP_MAX (size, 1);
if (r->_mp_alloc)
- r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size);
+ r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
else
- r->_mp_d = gmp_xalloc_limbs (size);
+ r->_mp_d = gmp_alloc_limbs (size);
r->_mp_alloc = size;
if (GMP_ABS (r->_mp_size) > size)
@@ -3096,7 +3109,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
one, using a *normalized* m. */
minv.shift = 0;
- tp = gmp_xalloc_limbs (mn);
+ tp = gmp_alloc_limbs (mn);
gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
mp = tp;
}
@@ -3162,7 +3175,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
}
if (tp)
- gmp_free (tp);
+ gmp_free_limbs (tp, mn);
mpz_swap (r, tr);
mpz_clear (tr);
@@ -4166,7 +4179,7 @@ mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
size_t
mpz_sizeinbase (const mpz_t u, int base)
{
- mp_size_t un;
+ mp_size_t un, tn;
mp_srcptr up;
mp_ptr tp;
mp_bitcnt_t bits;
@@ -4199,20 +4212,21 @@ mpz_sizeinbase (const mpz_t u, int base)
10. */
}
- tp = gmp_xalloc_limbs (un);
+ tp = gmp_alloc_limbs (un);
mpn_copyi (tp, up, un);
mpn_div_qr_1_invert (&bi, base);
+ tn = un;
ndigits = 0;
do
{
ndigits++;
- mpn_div_qr_1_preinv (tp, tp, un, &bi);
- un -= (tp[un-1] == 0);
+ mpn_div_qr_1_preinv (tp, tp, tn, &bi);
+ tn -= (tp[tn-1] == 0);
}
- while (un > 0);
+ while (tn > 0);
- gmp_free (tp);
+ gmp_free_limbs (tp, un);
return ndigits;
}
@@ -4222,7 +4236,7 @@ mpz_get_str (char *sp, int base, const mpz_t u)
unsigned bits;
const char *digits;
mp_size_t un;
- size_t i, sn;
+ size_t i, sn, osn;
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (base > 1)
@@ -4243,15 +4257,19 @@ mpz_get_str (char *sp, int base, const mpz_t u)
sn = 1 + mpz_sizeinbase (u, base);
if (!sp)
- sp = (char *) gmp_xalloc (1 + sn);
-
+ {
+ osn = 1 + sn;
+ sp = (char *) gmp_alloc (osn);
+ }
+ else
+ osn = 0;
un = GMP_ABS (u->_mp_size);
if (un == 0)
{
sp[0] = '0';
- sp[1] = '\0';
- return sp;
+ sn = 1;
+ goto ret;
}
i = 0;
@@ -4270,17 +4288,20 @@ mpz_get_str (char *sp, int base, const mpz_t u)
mp_ptr tp;
mpn_get_base_info (&info, base);
- tp = gmp_xalloc_limbs (un);
+ tp = gmp_alloc_limbs (un);
mpn_copyi (tp, u->_mp_d, un);
sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un);
- gmp_free (tp);
+ gmp_free_limbs (tp, un);
}
for (; i < sn; i++)
sp[i] = digits[(unsigned char) sp[i]];
+ret:
sp[sn] = '\0';
+ if (osn && osn != sn + 1)
+ sp = gmp_realloc(sp, osn, sn + 1);
return sp;
}
@@ -4290,7 +4311,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
unsigned bits, value_of_a;
mp_size_t rn, alloc;
mp_ptr rp;
- size_t dn;
+ size_t dn, sn;
int sign;
unsigned char *dp;
@@ -4328,7 +4349,8 @@ mpz_set_str (mpz_t r, const char *sp, int base)
r->_mp_size = 0;
return -1;
}
- dp = (unsigned char *) gmp_xalloc (strlen (sp));
+ sn = strlen(sp);
+ dp = (unsigned char *) gmp_alloc (sn);
value_of_a = (base > 36) ? 36 : 10;
for (dn = 0; *sp; sp++)
@@ -4348,7 +4370,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
if (digit >= (unsigned) base)
{
- gmp_free (dp);
+ gmp_free (dp, sn);
r->_mp_size = 0;
return -1;
}
@@ -4358,7 +4380,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
if (!dn)
{
- gmp_free (dp);
+ gmp_free (dp, sn);
r->_mp_size = 0;
return -1;
}
@@ -4382,7 +4404,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
rn -= rp[rn-1] == 0;
}
assert (rn <= alloc);
- gmp_free (dp);
+ gmp_free (dp, sn);
r->_mp_size = sign ? - rn : rn;
@@ -4400,13 +4422,13 @@ size_t
mpz_out_str (FILE *stream, int base, const mpz_t x)
{
char *str;
- size_t len;
+ size_t len, n;
str = mpz_get_str (NULL, base, x);
len = strlen (str);
- len = fwrite (str, 1, len, stream);
- gmp_free (str);
- return len;
+ n = fwrite (str, 1, len, stream);
+ gmp_free (str, len + 1);
+ return n;
}
@@ -4534,7 +4556,7 @@ mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
if (!r)
- r = gmp_xalloc (count * size);
+ r = gmp_alloc (count * size);
if (endian == 0)
endian = gmp_detect_endian ();
diff --git a/mini-gmp/mini-mpq.c b/mini-gmp/mini-mpq.c
index fd9b43990..fb0010653 100644
--- a/mini-gmp/mini-mpq.c
+++ b/mini-gmp/mini-mpq.c
@@ -498,9 +498,9 @@ mpq_get_str (char *sp, int base, const mpq_t q)
mp_get_memory_functions (NULL, &gmp_reallocate_func, &gmp_free_func);
lden = strlen (rden) + 1;
- res = (char *) gmp_reallocate_func (res, 0, (lden + len) * sizeof (char));
+ res = (char *) gmp_reallocate_func (res, len, (lden + len) * sizeof (char));
memcpy (res + len, rden, lden);
- gmp_free_func (rden, 0);
+ gmp_free_func (rden, lden);
}
res [len - 1] = '/';
@@ -511,15 +511,15 @@ size_t
mpq_out_str (FILE *stream, int base, const mpq_t x)
{
char * str;
- size_t len;
+ size_t len, n;
void (*gmp_free_func) (void *, size_t);
str = mpq_get_str (NULL, base, x);
len = strlen (str);
- len = fwrite (str, 1, len, stream);
+ n = fwrite (str, 1, len, stream);
mp_get_memory_functions (NULL, NULL, &gmp_free_func);
- gmp_free_func (str, 0);
- return len;
+ gmp_free_func (str, len + 1);
+ return n;
}
int
@@ -540,11 +540,11 @@ mpq_set_str (mpq_t r, const char *sp, int base)
mp_get_memory_functions (&gmp_allocate_func, NULL, &gmp_free_func);
numlen = slash - sp;
- num = (char *) gmp_allocate_func ((numlen + 1) * sizeof (char));
+ num = (char *) gmp_allocate_func (numlen + 1);
memcpy (num, sp, numlen);
num[numlen] = '\0';
ret = mpz_set_str (mpq_numref(r), num, base);
- gmp_free_func (num, 0);
+ gmp_free_func (num, numlen + 1);
if (ret != 0)
return ret;
diff --git a/mini-gmp/tests/t-double.c b/mini-gmp/tests/t-double.c
index 9a1aa8f11..fa40e3193 100644
--- a/mini-gmp/tests/t-double.c
+++ b/mini-gmp/tests/t-double.c
@@ -156,7 +156,7 @@ testmain (int argc, char **argv)
values[i].d, s, values[i].s);
abort ();
}
- testfree (s);
+ testfree (s, strlen(s) + 1);
mpz_clear (x);
}
diff --git a/mini-gmp/tests/t-mpq_str.c b/mini-gmp/tests/t-mpq_str.c
index 7c69153a7..84a1feb84 100644
--- a/mini-gmp/tests/t-mpq_str.c
+++ b/mini-gmp/tests/t-mpq_str.c
@@ -1,6 +1,6 @@
/*
-Copyright 2012-2014, 2016, 2018 Free Software Foundation, Inc.
+Copyright 2012-2014, 2016, 2018, 2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
@@ -144,7 +144,7 @@ testmain (int argc, char **argv)
char *ap;
char *bp;
char *rp;
- size_t rn, arn;
+ size_t rn;
mpq_t a, b;
@@ -173,7 +173,6 @@ testmain (int argc, char **argv)
}
rn = strlen (rp);
- arn = rn - (rp[0] == '-');
bp = mpq_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
if (strcmp (bp, rp))
@@ -244,7 +243,7 @@ testmain (int argc, char **argv)
free (ap);
free (rp);
- testfree (bp);
+ testfree (bp, strlen(bp) + 1);
}
}
mpq_clear (a);
diff --git a/mini-gmp/tests/t-str.c b/mini-gmp/tests/t-str.c
index 1e78676ee..2aa67d01d 100644
--- a/mini-gmp/tests/t-str.c
+++ b/mini-gmp/tests/t-str.c
@@ -140,7 +140,7 @@ testmain (int argc, char **argv)
char *ap;
char *bp;
char *rp;
- size_t bn, rn, arn;
+ size_t bn, rn, arn, bps;
mpz_t a, b;
@@ -182,6 +182,7 @@ testmain (int argc, char **argv)
abort ();
}
bp = mpz_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
+ bps = strlen(bp) + 1;
if (strcmp (bp, rp))
{
fprintf (stderr, "mpz_get_str failed:\n");
@@ -311,7 +312,7 @@ testmain (int argc, char **argv)
}
free (ap);
free (rp);
- testfree (bp);
+ testfree (bp, bps);
}
}
mpz_clear (a);
diff --git a/mini-gmp/tests/testutils.c b/mini-gmp/tests/testutils.c
index b131a9e47..46e368a91 100644
--- a/mini-gmp/tests/testutils.c
+++ b/mini-gmp/tests/testutils.c
@@ -84,8 +84,16 @@ tu_alloc (size_t size)
static void *
tu_realloc (void *p, size_t old_size, size_t new_size)
{
- size_t *block = block_check (p);
- block = (size_t *) realloc (block, sizeof(size_t) + new_size + sizeof(block_end));
+ size_t *block;
+ size_t *old_block = block_check (p);
+ if (old_block[0] != old_size)
+ {
+ fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
+ (long)old_block[0], (long)old_size);
+ abort ();
+ }
+
+ block = (size_t *) realloc (old_block, sizeof(size_t) + new_size + sizeof(block_end));
if (!block)
{
fprintf (stderr, "Virtual memory exhausted.\n");
@@ -98,17 +106,24 @@ tu_realloc (void *p, size_t old_size, size_t new_size)
static void
tu_free (void *p, size_t old_size)
{
- free (block_check (p));
+ size_t *old_block = block_check (p);
+ if (old_block[0] != old_size && old_size != 0)
+ {
+ fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
+ (long)old_block[0], (long)old_size);
+ abort ();
+ }
+ free (old_block);
}
/* Free memory allocated via mini-gmp allocation function. */
void
-testfree (void *p)
+testfree (void *p, size_t size)
{
void (*freefunc) (void *, size_t);
mp_get_memory_functions (NULL, NULL, &freefunc);
- freefunc (p, 0);
+ freefunc (p, size);
}
int
@@ -158,7 +173,7 @@ dump (const char *label, const mpz_t x)
{
char *buf = mpz_get_str (NULL, 16, x);
fprintf (stderr, "%s: %s\n", label, buf);
- testfree (buf);
+ testfree (buf, strlen(buf) + 1);
}
void
diff --git a/mini-gmp/tests/testutils.h b/mini-gmp/tests/testutils.h
index e565ac372..bcc08c577 100644
--- a/mini-gmp/tests/testutils.h
+++ b/mini-gmp/tests/testutils.h
@@ -28,7 +28,7 @@ void testmain (int argc, char **argv);
void testhalves (int count, void (*tested_fun) (int));
-void testfree (void *p);
+void testfree (void *p, size_t size);
void
dump (const char *label, const mpz_t x);