Issue #9530: Fix undefined behaviour due to signed overflow in Python/formatter_unicode.c.
This commit is contained in:
parent
0a54cf12a0
commit
47862d4c0e
|
@ -51,7 +51,7 @@ static int
|
||||||
get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
|
get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
|
||||||
Py_ssize_t *result)
|
Py_ssize_t *result)
|
||||||
{
|
{
|
||||||
Py_ssize_t accumulator, digitval, oldaccumulator;
|
Py_ssize_t accumulator, digitval;
|
||||||
int numdigits;
|
int numdigits;
|
||||||
accumulator = numdigits = 0;
|
accumulator = numdigits = 0;
|
||||||
for (;;(*pos)++, numdigits++) {
|
for (;;(*pos)++, numdigits++) {
|
||||||
|
@ -61,19 +61,17 @@ get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
|
||||||
if (digitval < 0)
|
if (digitval < 0)
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
This trick was copied from old Unicode format code. It's cute,
|
Detect possible overflow before it happens:
|
||||||
but would really suck on an old machine with a slow divide
|
|
||||||
implementation. Fortunately, in the normal case we do not
|
accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
|
||||||
expect too many digits.
|
accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
|
||||||
*/
|
*/
|
||||||
oldaccumulator = accumulator;
|
if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
|
||||||
accumulator *= 10;
|
|
||||||
if ((accumulator+10)/10 != oldaccumulator+1) {
|
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"Too many decimal digits in format string");
|
"Too many decimal digits in format string");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
accumulator += digitval;
|
accumulator = accumulator * 10 + digitval;
|
||||||
}
|
}
|
||||||
*result = accumulator;
|
*result = accumulator;
|
||||||
return numdigits;
|
return numdigits;
|
||||||
|
|
Loading…
Reference in New Issue