summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_builtin.py6
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/pystrtod.c73
3 files changed, 32 insertions, 50 deletions
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index c8a4822c7f..62489729a0 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -545,6 +545,8 @@ class BuiltinTest(unittest.TestCase):
self.assertEqual(float(314), 314.0)
self.assertEqual(float(314L), 314.0)
self.assertEqual(float(" 3.14 "), 3.14)
+ self.assertRaises(ValueError, float, " 0x3.1 ")
+ self.assertRaises(ValueError, float, " -0x3.p-1 ")
if have_unicode:
self.assertEqual(float(unicode(" 3.14 ")), 3.14)
self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
@@ -572,8 +574,8 @@ class BuiltinTest(unittest.TestCase):
self.assertEqual(float(" 3,14 "), 3.14)
self.assertEqual(float(" +3,14 "), 3.14)
self.assertEqual(float(" -3,14 "), -3.14)
- self.assertEqual(float(" 0x3.1 "), 3.0625)
- self.assertEqual(float(" -0x3.p-1 "), -1.5)
+ self.assertRaises(ValueError, float, " 0x3.1 ")
+ self.assertRaises(ValueError, float, " -0x3.p-1 ")
self.assertEqual(float(" 25.e-1 "), 2.5)
self.assertEqual(fcmp(float(" .25e-1 "), .025), 0)
finally:
diff --git a/Misc/NEWS b/Misc/NEWS
index 8b79fb6ce5..1db35f44b9 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1?
Core and builtins
-----------------
+- Support for converting hex strings to floats no longer works.
+ This was not portable. float('0x3') now raises a ValueError.
+
- Patch #1382163: Expose Subversion revision number to Python. New C API
function Py_GetBuildNumber(). New attribute sys.build_number. Build number
is now displayed in interactive prompt banner.
diff --git a/Python/pystrtod.c b/Python/pystrtod.c
index ab2579982e..19f25dab97 100644
--- a/Python/pystrtod.c
+++ b/Python/pystrtod.c
@@ -38,8 +38,7 @@
* Return value: the #gdouble value.
**/
double
-PyOS_ascii_strtod(const char *nptr,
- char **endptr)
+PyOS_ascii_strtod(const char *nptr, char **endptr)
{
char *fail_pos;
double val;
@@ -49,7 +48,6 @@ PyOS_ascii_strtod(const char *nptr,
const char *p, *decimal_point_pos;
const char *end = NULL; /* Silence gcc */
-/* g_return_val_if_fail (nptr != NULL, 0); */
assert(nptr != NULL);
fail_pos = NULL;
@@ -73,64 +71,36 @@ PyOS_ascii_strtod(const char *nptr,
if (*p == '+' || *p == '-')
p++;
- if (p[0] == '0' &&
- (p[1] == 'x' || p[1] == 'X'))
+ while (ISDIGIT(*p))
+ p++;
+
+ if (*p == '.')
{
- p += 2;
- /* HEX - find the (optional) decimal point */
+ decimal_point_pos = p++;
- while (ISXDIGIT(*p))
+ while (ISDIGIT(*p))
p++;
- if (*p == '.')
- {
- decimal_point_pos = p++;
-
- while (ISXDIGIT(*p))
- p++;
-
- if (*p == 'p' || *p == 'P')
- p++;
- if (*p == '+' || *p == '-')
- p++;
- while (ISDIGIT(*p))
- p++;
- end = p;
- }
- }
- else
- {
+ if (*p == 'e' || *p == 'E')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
while (ISDIGIT(*p))
p++;
-
- if (*p == '.')
- {
- decimal_point_pos = p++;
-
- while (ISDIGIT(*p))
- p++;
-
- if (*p == 'e' || *p == 'E')
- p++;
- if (*p == '+' || *p == '-')
- p++;
- while (ISDIGIT(*p))
- p++;
- end = p;
- }
+ end = p;
}
- /* For the other cases, we need not convert the decimal point */
+ /* For the other cases, we need not convert the decimal point */
}
- /* Set errno to zero, so that we can distinguish zero results
- and underflows */
+ /* Set errno to zero, so that we can distinguish zero results
+ and underflows */
errno = 0;
if (decimal_point_pos)
{
char *copy, *c;
- /* We need to convert the '.' to the locale specific decimal point */
+ /* We need to convert the '.' to the locale specific decimal point */
copy = malloc(end - nptr + 1 + decimal_point_len);
c = copy;
@@ -155,8 +125,15 @@ PyOS_ascii_strtod(const char *nptr,
free(copy);
}
- else
- val = strtod(nptr, &fail_pos);
+ else {
+ unsigned i = 0;
+ if (nptr[i] == '-')
+ i++;
+ if (nptr[i] == '0' && (nptr[i+1] == 'x' || nptr[i+1] == 'X'))
+ fail_pos = nptr;
+ else
+ val = strtod(nptr, &fail_pos);
+ }
if (endptr)
*endptr = fail_pos;