[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