From f9a5a8e0aff67061583b31afa114a6d025b1680d Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Wed, 26 May 2010 20:07:58 +0000 Subject: [PATCH] Issue #2844: Make int('42', n) consistently raise ValueError for invalid integers n (including n = -909). --- Lib/test/test_long.py | 10 ++++++++++ Misc/NEWS | 3 +++ Objects/longobject.c | 29 ++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index c47b8e3505c0e2..133702ec5f2e17 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -345,6 +345,16 @@ def test_long(self): self.assertRaises(ValueError, int, '08', 0) self.assertRaises(ValueError, int, '-012395', 0) + # invalid bases + invalid_bases = [-909, + 2**31-1, 2**31, -2**31, -2**31-1, + 2**63-1, 2**63, -2**63, -2**63-1, + 2**100, -2**100, + ] + for base in invalid_bases: + self.assertRaises(ValueError, int, '42', base) + + def test_conversion(self): class JustLong: diff --git a/Misc/NEWS b/Misc/NEWS index 6899442224ef24..bbb46e0420fd2a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 1? Core and Builtins ----------------- +- Issue #2844: Make int('42', n) consistently raise ValueError for + invalid integers n (including n = -909). + - Issue #8188: Introduce a new scheme for computing hashes of numbers (instances of int, float, complex, decimal.Decimal and fractions.Fraction) that makes it easy to maintain the invariant diff --git a/Objects/longobject.c b/Objects/longobject.c index 3eb0c44b58cf0c..ed41010b04a17d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4098,23 +4098,34 @@ long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *x = NULL; - int base = -909; /* unlikely! */ + PyObject *obase = NULL, *x = NULL; + long base; + int overflow; static char *kwlist[] = {"x", "base", 0}; if (type != &PyLong_Type) return long_subtype_new(type, args, kwds); /* Wimp out */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, - &x, &base)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:int", kwlist, + &x, &obase)) return NULL; if (x == NULL) return PyLong_FromLong(0L); - if (base == -909) + if (obase == NULL) return PyNumber_Long(x); - else if (PyUnicode_Check(x)) + + base = PyLong_AsLongAndOverflow(obase, &overflow); + if (base == -1 && PyErr_Occurred()) + return NULL; + if (overflow || (base != 0 && base < 2) || base > 36) { + PyErr_SetString(PyExc_ValueError, + "int() arg 2 must be >= 2 and <= 36"); + return NULL; + } + + if (PyUnicode_Check(x)) return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x), PyUnicode_GET_SIZE(x), - base); + (int)base); else if (PyByteArray_Check(x) || PyBytes_Check(x)) { /* Since PyLong_FromString doesn't have a length parameter, * check here for possible NULs in the string. */ @@ -4129,10 +4140,10 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) x is a bytes or buffer, *and* a base is given. */ PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", - base, x); + (int)base, x); return NULL; } - return PyLong_FromString(string, NULL, base); + return PyLong_FromString(string, NULL, (int)base); } else { PyErr_SetString(PyExc_TypeError,