diff options
-rw-r--r-- | mini-gmp/ChangeLog | 20 | ||||
-rw-r--r-- | mini-gmp/README | 7 | ||||
-rw-r--r-- | mini-gmp/mini-gmp.c | 102 | ||||
-rw-r--r-- | mini-gmp/mini-mpq.c | 16 | ||||
-rw-r--r-- | mini-gmp/tests/t-double.c | 2 | ||||
-rw-r--r-- | mini-gmp/tests/t-mpq_str.c | 7 | ||||
-rw-r--r-- | mini-gmp/tests/t-str.c | 5 | ||||
-rw-r--r-- | mini-gmp/tests/testutils.c | 27 | ||||
-rw-r--r-- | mini-gmp/tests/testutils.h | 2 |
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); |