mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Proactive reliability fix for broken FPUs: The base conversion functions
use log10() to calculate the size of the output array. The current code has been tested on x86/amd64 (and to a lesser extent on qemu-mips qemu-sparc) and produces sufficiently large values for all inputs tested so far (coefficient sizes of 10**18 - 1 are hard to test exhaustively). The new code does not rely on the correctness of log10() and resizes the output arrays if the allocated space is insufficient.
This commit is contained in:
parent
e38c98f974
commit
c35a8e5c98
5 changed files with 430 additions and 219 deletions
|
@ -3203,7 +3203,8 @@ static PyObject *
|
|||
dec_as_long(PyObject *dec, PyObject *context, int round)
|
||||
{
|
||||
PyLongObject *pylong;
|
||||
size_t maxsize, n;
|
||||
digit *ob_digit;
|
||||
size_t n;
|
||||
Py_ssize_t i;
|
||||
mpd_t *x;
|
||||
mpd_context_t workctx;
|
||||
|
@ -3234,32 +3235,33 @@ dec_as_long(PyObject *dec, PyObject *context, int round)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
maxsize = mpd_sizeinbase(x, PyLong_BASE);
|
||||
if (maxsize > PY_SSIZE_T_MAX) {
|
||||
mpd_del(x);
|
||||
status = 0;
|
||||
ob_digit = NULL;
|
||||
#if PYLONG_BITS_IN_DIGIT == 30
|
||||
n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status);
|
||||
#elif PYLONG_BITS_IN_DIGIT == 15
|
||||
n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status);
|
||||
#else
|
||||
#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
|
||||
#endif
|
||||
|
||||
if (n == SIZE_MAX) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
pylong = _PyLong_New(maxsize);
|
||||
if (pylong == NULL) {
|
||||
mpd_del(x);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
#if PYLONG_BITS_IN_DIGIT == 30
|
||||
n = mpd_qexport_u32(pylong->ob_digit, maxsize, PyLong_BASE, x, &status);
|
||||
#elif PYLONG_BITS_IN_DIGIT == 15
|
||||
n = mpd_qexport_u16(pylong->ob_digit, maxsize, PyLong_BASE, x, &status);
|
||||
#else
|
||||
#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
|
||||
#endif
|
||||
if (dec_addstatus(context, status)) {
|
||||
Py_DECREF((PyObject *) pylong);
|
||||
assert(n > 0);
|
||||
pylong = _PyLong_New(n);
|
||||
if (pylong == NULL) {
|
||||
mpd_free(ob_digit);
|
||||
mpd_del(x);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(pylong->ob_digit, ob_digit, n * sizeof(digit));
|
||||
mpd_free(ob_digit);
|
||||
|
||||
i = n;
|
||||
while ((i > 0) && (pylong->ob_digit[i-1] == 0)) {
|
||||
i--;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue