Skip to content

Commit c6a8db9

Browse files
committed
gh-158446: Also bound large negative precisions; broaden NEWS wording
Make the PyOS_double_to_string() precision check symmetric so that C callers passing a huge negative precision cannot reach the remaining precision arithmetic either. Reword the NEWS entry: the limit applies to float and complex formatting regardless of presentation type or value.
1 parent 2f1e70c commit c6a8db9

2 files changed

Lines changed: 15 additions & 11 deletions

File tree

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Fix a crash or incorrect output when formatting a :class:`float` using the
2-
``'f'``, ``'e'`` or ``'g'`` presentation types with a precision close to the
3-
platform's ``INT_MAX``. Such precisions now raise :exc:`ValueError`, as
4-
precisions above ``INT_MAX`` already did.
1+
Fix a crash or incorrect output that could occur when formatting a
2+
:class:`float` or :class:`complex` with a precision close to the platform's
3+
``INT_MAX``. :c:func:`PyOS_double_to_string` now raises :exc:`ValueError` for
4+
any precision of that magnitude, regardless of presentation type or value, as
5+
the format string parsers already did for precisions above ``INT_MAX``.

‎Python/pystrtod.c‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,12 @@ _Py_string_to_number_with_underscores(
401401
return NULL;
402402
}
403403

404-
/* Largest precision accepted by PyOS_double_to_string(). The output buffer
405-
sizes computed below and within _Py_dg_dtoa() use int and Py_ssize_t
406-
arithmetic on roughly precision + (digits before the point, at most
407-
DBL_MAX_10_EXP + 1 == 309) + a few bytes of sign, point and exponent.
408-
Staying this far below INT_MAX keeps all of those sums in range. */
404+
/* Largest precision magnitude accepted by PyOS_double_to_string(). The
405+
output buffer sizes computed below and within _Py_dg_dtoa() use int and
406+
Py_ssize_t arithmetic on roughly precision + (digits before the point, at
407+
most DBL_MAX_10_EXP + 1 == 309) + a few bytes of sign, point and exponent.
408+
Staying this far inside the int range keeps all of those sums in range.
409+
(Only C callers can pass a negative precision.) */
409410
#define DOUBLE_TO_STRING_PRECISION_MAX (INT_MAX - 1024)
410411

411412
#if _PY_SHORT_FLOAT_REPR == 0
@@ -773,7 +774,8 @@ char * PyOS_double_to_string(double val,
773774
int t, exp;
774775
int upper = 0;
775776

776-
if (precision > DOUBLE_TO_STRING_PRECISION_MAX) {
777+
if (precision > DOUBLE_TO_STRING_PRECISION_MAX
778+
|| precision < -DOUBLE_TO_STRING_PRECISION_MAX) {
777779
PyErr_SetString(PyExc_ValueError, "precision too big");
778780
return NULL;
779781
}
@@ -1239,7 +1241,8 @@ char * PyOS_double_to_string(double val,
12391241
const char * const *float_strings = lc_float_strings;
12401242
int mode;
12411243

1242-
if (precision > DOUBLE_TO_STRING_PRECISION_MAX) {
1244+
if (precision > DOUBLE_TO_STRING_PRECISION_MAX
1245+
|| precision < -DOUBLE_TO_STRING_PRECISION_MAX) {
12431246
PyErr_SetString(PyExc_ValueError, "precision too big");
12441247
return NULL;
12451248
}

0 commit comments

Comments
 (0)