[packages/mpdecimal] - added cpython patch (div and sqrt memory exhaustion fix from CPython); release 2
qboosh
qboosh at pld-linux.org
Tue Apr 21 21:07:56 CEST 2020
commit 9905bfbfc1d056ae49f6eb2e665ceef977af3f29
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Tue Apr 21 21:08:06 2020 +0200
- added cpython patch (div and sqrt memory exhaustion fix from CPython); release 2
mpdecimal-cpython.patch | 113 ++++++++++++++++++++++++++++++++++++++++++++++++
mpdecimal.spec | 4 +-
2 files changed, 116 insertions(+), 1 deletion(-)
---
diff --git a/mpdecimal.spec b/mpdecimal.spec
index 13b1100..a827d6b 100644
--- a/mpdecimal.spec
+++ b/mpdecimal.spec
@@ -2,12 +2,13 @@ Summary: Fast arbitrary precision correctly-rounded decimal floating point arith
Summary(pl.UTF-8): Szybka arytmetyka zmiennoprzecinkowa dowolnej precyzji z właściwym zaokrąglaniem
Name: mpdecimal
Version: 2.4.2
-Release: 1
+Release: 2
License: BSD
Group: Libraries
#Source0Download: http://www.bytereef.org/mpdecimal/download.html
Source0: http://www.bytereef.org/software/mpdecimal/releases/%{name}-%{version}.tar.gz
# Source0-md5: aa63cab5d06a96855a44da2db90a29d9
+Patch0: %{name}-cpython.patch
URL: http://www.bytereef.org/mpdecimal/
BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
@@ -63,6 +64,7 @@ Dokumentacja API biblioteki libmpdec.
%prep
%setup -q
+%patch -p0
%build
%configure
diff --git a/mpdecimal-cpython.patch b/mpdecimal-cpython.patch
new file mode 100644
index 0000000..94cdf11
--- /dev/null
+++ b/mpdecimal-cpython.patch
@@ -0,0 +1,113 @@
+From 90930e65455f60216f09d175586139242dbba260 Mon Sep 17 00:00:00 2001
+From: Stefan Krah <skrah at bytereef.org>
+Date: Fri, 21 Feb 2020 01:52:47 +0100
+Subject: [PATCH] bpo-39576: Prevent memory error for overly optimistic
+ precisions (GH-18581)
+
+---
+ Lib/test/test_decimal.py | 35 +++++++
+ Modules/_decimal/libmpdec/mpdecimal.c | 77 +++++++++++++-
+ Modules/_decimal/tests/deccheck.py | 139 +++++++++++++++++++++++++-
+ 3 files changed, 245 insertions(+), 6 deletions(-)
+
+#diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c
+--- libmpdec/mpdecimal.c
++++ libmpdec/mpdecimal.c
+@@ -3781,6 +3781,43 @@ mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
+ const mpd_context_t *ctx, uint32_t *status)
+ {
+ _mpd_qdiv(SET_IDEAL_EXP, q, a, b, ctx, status);
++
++ if (*status & MPD_Malloc_error) {
++ /* Inexact quotients (the usual case) fill the entire context precision,
++ * which can lead to malloc() failures for very high precisions. Retry
++ * the operation with a lower precision in case the result is exact.
++ *
++ * We need an upper bound for the number of digits of a_coeff / b_coeff
++ * when the result is exact. If a_coeff' * 1 / b_coeff' is in lowest
++ * terms, then maxdigits(a_coeff') + maxdigits(1 / b_coeff') is a suitable
++ * bound.
++ *
++ * 1 / b_coeff' is exact iff b_coeff' exclusively has prime factors 2 or 5.
++ * The largest amount of digits is generated if b_coeff' is a power of 2 or
++ * a power of 5 and is less than or equal to log5(b_coeff') <= log2(b_coeff').
++ *
++ * We arrive at a total upper bound:
++ *
++ * maxdigits(a_coeff') + maxdigits(1 / b_coeff') <=
++ * a->digits + log2(b_coeff) =
++ * a->digits + log10(b_coeff) / log10(2) <=
++ * a->digits + b->digits * 4;
++ */
++ uint32_t workstatus = 0;
++ mpd_context_t workctx = *ctx;
++ workctx.prec = a->digits + b->digits * 4;
++ if (workctx.prec >= ctx->prec) {
++ return; /* No point in retrying, keep the original error. */
++ }
++
++ _mpd_qdiv(SET_IDEAL_EXP, q, a, b, &workctx, &workstatus);
++ if (workstatus == 0) { /* The result is exact, unrounded, normal etc. */
++ *status = 0;
++ return;
++ }
++
++ mpd_seterror(q, *status, status);
++ }
+ }
+
+ /* Internal function. */
+@@ -7702,9 +7739,9 @@ mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
+ /* END LIBMPDEC_ONLY */
+
+ /* Algorithm from decimal.py */
+-void
+-mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
+- uint32_t *status)
++static void
++_mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
++ uint32_t *status)
+ {
+ mpd_context_t maxcontext;
+ MPD_NEW_STATIC(c,0,0,0,0);
+@@ -7836,6 +7873,40 @@ mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
+ goto out;
+ }
+
++void
++mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
++ uint32_t *status)
++{
++ _mpd_qsqrt(result, a, ctx, status);
++
++ if (*status & (MPD_Malloc_error|MPD_Division_impossible)) {
++ /* The above conditions can occur at very high context precisions
++ * if intermediate values get too large. Retry the operation with
++ * a lower context precision in case the result is exact.
++ *
++ * If the result is exact, an upper bound for the number of digits
++ * is the number of digits in the input.
++ *
++ * NOTE: sqrt(40e9) = 2.0e+5 /\ digits(40e9) = digits(2.0e+5) = 2
++ */
++ uint32_t workstatus = 0;
++ mpd_context_t workctx = *ctx;
++ workctx.prec = a->digits;
++
++ if (workctx.prec >= ctx->prec) {
++ return; /* No point in repeating this, keep the original error. */
++ }
++
++ _mpd_qsqrt(result, a, &workctx, &workstatus);
++ if (workstatus == 0) {
++ *status = 0;
++ return;
++ }
++
++ mpd_seterror(result, *status, status);
++ }
++}
++
+
+ /******************************************************************************/
+ /* Base conversions */
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/mpdecimal.git/commitdiff/9905bfbfc1d056ae49f6eb2e665ceef977af3f29
More information about the pld-cvs-commit
mailing list