Skip to content

Commit c04c7c5

Browse files
committed
Issue #7117: Use PyOS_string_to_double instead of PyOS_ascii_strtod in
complexobject.c. Also remove length restriction on unicode inputs to the complex constructor.
1 parent 8568b19 commit c04c7c5

3 files changed

Lines changed: 36 additions & 17 deletions

File tree

‎Lib/test/test_complex.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ def split_zeros(x):
306306
self.assertRaises(ValueError, complex, "1+(2j)")
307307
self.assertRaises(ValueError, complex, "(1+2j)123")
308308
if test_support.have_unicode:
309-
self.assertRaises(ValueError, complex, unicode("1"*500))
310309
self.assertRaises(ValueError, complex, unicode("x"))
311310
self.assertRaises(ValueError, complex, "1j+2")
312311
self.assertRaises(ValueError, complex, "1e1ej")
@@ -317,6 +316,10 @@ def split_zeros(x):
317316
self.assertRaises(ValueError, complex, "1.11.1j")
318317
self.assertRaises(ValueError, complex, "1e1.1j")
319318

319+
if test_support.have_unicode:
320+
# check that complex accepts long unicode strings
321+
self.assertEqual(type(complex(unicode("1"*500))), complex)
322+
320323
class EvilExc(Exception):
321324
pass
322325

‎Misc/NEWS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
1212
Core and Builtins
1313
-----------------
1414

15+
- Remove length limitation when constructing a complex number from a
16+
unicode string.
17+
1518
- Removed _PyOS_double_to_string. Use PyOS_double_to_string
1619
instead. This is in preparation for (but not strictly related to)
1720
issue #7117, short float repr.

‎Objects/complexobject.c‎

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
921921
double x=0.0, y=0.0, z;
922922
int got_bracket=0;
923923
#ifdef Py_USING_UNICODE
924-
char s_buffer[256];
924+
char *s_buffer = NULL;
925925
#endif
926926
Py_ssize_t len;
927927

@@ -931,16 +931,14 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
931931
}
932932
#ifdef Py_USING_UNICODE
933933
else if (PyUnicode_Check(v)) {
934-
if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) {
935-
PyErr_SetString(PyExc_ValueError,
936-
"complex() literal too large to convert");
937-
return NULL;
938-
}
934+
s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);
935+
if (s_buffer == NULL)
936+
return PyErr_NoMemory();
939937
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
940938
PyUnicode_GET_SIZE(v),
941939
s_buffer,
942940
NULL))
943-
return NULL;
941+
goto error;
944942
s = s_buffer;
945943
len = strlen(s);
946944
}
@@ -985,21 +983,26 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
985983
*/
986984

987985
/* first look for forms starting with <float> */
988-
errno = 0;
989-
z = PyOS_ascii_strtod(s, &end);
990-
if (end == s && errno == ENOMEM)
991-
return PyErr_NoMemory();
992-
986+
z = PyOS_string_to_double(s, &end, NULL);
987+
if (z == -1.0 && PyErr_Occurred()) {
988+
if (PyErr_ExceptionMatches(PyExc_ValueError))
989+
PyErr_Clear();
990+
else
991+
goto error;
992+
}
993993
if (end != s) {
994994
/* all 4 forms starting with <float> land here */
995995
s = end;
996996
if (*s == '+' || *s == '-') {
997997
/* <float><signed-float>j | <float><sign>j */
998998
x = z;
999-
errno = 0;
1000-
y = PyOS_ascii_strtod(s, &end);
1001-
if (end == s && errno == ENOMEM)
1002-
return PyErr_NoMemory();
999+
y = PyOS_string_to_double(s, &end, NULL);
1000+
if (y == -1.0 && PyErr_Occurred()) {
1001+
if (PyErr_ExceptionMatches(PyExc_ValueError))
1002+
PyErr_Clear();
1003+
else
1004+
goto error;
1005+
}
10031006
if (end != s)
10041007
/* <float><signed-float>j */
10051008
s = end;
@@ -1053,11 +1056,21 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
10531056
if (s-start != len)
10541057
goto parse_error;
10551058

1059+
1060+
#ifdef Py_USING_UNICODE
1061+
if (s_buffer)
1062+
PyMem_FREE(s_buffer);
1063+
#endif
10561064
return complex_subtype_from_doubles(type, x, y);
10571065

10581066
parse_error:
10591067
PyErr_SetString(PyExc_ValueError,
10601068
"complex() arg is a malformed string");
1069+
error:
1070+
#ifdef Py_USING_UNICODE
1071+
if (s_buffer)
1072+
PyMem_FREE(s_buffer);
1073+
#endif
10611074
return NULL;
10621075
}
10631076

0 commit comments

Comments
 (0)