summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-04-20 21:19:14 (GMT)
committerBrett Cannon <brett@python.org>2012-04-20 21:19:14 (GMT)
commit5d5296d36e7be54141f06e79c4ab90a1ccde8544 (patch)
tree7f5abc5709cab118d6a450a378b51afa927bd195
parentbbdc9cd3d2cbdc2cc64d2945da175bdc18a93ce3 (diff)
parent9a359bd97f5fc0ab3ae830ad874eda6e5e76b14c (diff)
downloadcpython-5d5296d36e7be54141f06e79c4ab90a1ccde8544.zip
cpython-5d5296d36e7be54141f06e79c4ab90a1ccde8544.tar.gz
cpython-5d5296d36e7be54141f06e79c4ab90a1ccde8544.tar.bz2
Merge
-rw-r--r--Lib/test/test_long.py14
-rw-r--r--Misc/NEWS6
-rw-r--r--Objects/longobject.c61
3 files changed, 52 insertions, 29 deletions
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 05b3e3e..b417bea 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -1228,6 +1228,20 @@ class LongTest(unittest.TestCase):
self.assertRaises(TypeError, myint.from_bytes, 0, 'big')
self.assertRaises(TypeError, int.from_bytes, 0, 'big', True)
+ def test_access_to_nonexistent_digit_0(self):
+ # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that
+ # ob_digit[0] was being incorrectly accessed for instances of a
+ # subclass of int, with value 0.
+ class Integer(int):
+ def __new__(cls, value=0):
+ self = int.__new__(cls, value)
+ self.foo = 'foo'
+ return self
+
+ integers = [Integer(0) for i in range(1000)]
+ for n in map(int, integers):
+ self.assertEqual(n, 0)
+
def test_main():
support.run_unittest(LongTest)
diff --git a/Misc/NEWS b/Misc/NEWS
index 6d3410f..08a1dd3 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,12 @@ What's New in Python 3.3.0 Alpha 3?
Core and Builtins
-----------------
+- Issue #14630: Fix a memory access bug for instances of a subclass of int
+ with value 0.
+
+- Issue #14339: Speed improvements to bin, oct and hex functions. Patch by
+ Serhiy Storchaka.
+
- Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo.
Patch by Stefan Behnel.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index ab49f28..3630ae4 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -156,9 +156,7 @@ _PyLong_Copy(PyLongObject *src)
if (i < 0)
i = -(i);
if (i < 2) {
- sdigit ival = src->ob_digit[0];
- if (Py_SIZE(src) < 0)
- ival = -ival;
+ sdigit ival = MEDIUM_VALUE(src);
CHECK_SMALL_INT(ival);
}
result = _PyLong_New(i);
@@ -1672,11 +1670,10 @@ _PyLong_Format(PyObject *aa, int base)
{
register PyLongObject *a = (PyLongObject *)aa;
PyObject *v;
- Py_ssize_t i, sz;
+ Py_ssize_t sz;
Py_ssize_t size_a;
- char *p;
- char sign = '\0';
- char *buffer;
+ Py_UCS1 *p;
+ int negative;
int bits;
assert(base == 2 || base == 8 || base == 10 || base == 16);
@@ -1688,6 +1685,7 @@ _PyLong_Format(PyObject *aa, int base)
return NULL;
}
size_a = ABS(Py_SIZE(a));
+ negative = Py_SIZE(a) < 0;
/* Compute a rough upper bound for the length of the string */
switch (base) {
@@ -1704,33 +1702,40 @@ _PyLong_Format(PyObject *aa, int base)
assert(0); /* shouldn't ever get here */
bits = 0; /* to silence gcc warning */
}
- /* compute length of output string: allow 2 characters for prefix and
- 1 for possible '-' sign. */
- if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT / sizeof(Py_UCS4)) {
- PyErr_SetString(PyExc_OverflowError,
- "int is too large to format");
- return NULL;
+
+ /* Compute exact length 'sz' of output string. */
+ if (size_a == 0) {
+ sz = 3;
}
- /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below
- is safe from overflow */
- sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits;
- assert(sz >= 0);
- buffer = PyMem_Malloc(sz);
- if (buffer == NULL) {
- PyErr_NoMemory();
+ else {
+ Py_ssize_t size_a_in_bits;
+ /* Ensure overflow doesn't occur during computation of sz. */
+ if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) {
+ PyErr_SetString(PyExc_OverflowError,
+ "int is too large to format");
+ return NULL;
+ }
+ size_a_in_bits = (size_a - 1) * PyLong_SHIFT +
+ bits_in_digit(a->ob_digit[size_a - 1]);
+ /* Allow 2 characters for prefix and 1 for a '-' sign. */
+ sz = 2 + negative + (size_a_in_bits + (bits - 1)) / bits;
+ }
+
+ v = PyUnicode_New(sz, 'x');
+ if (v == NULL) {
return NULL;
}
- p = &buffer[sz];
- if (Py_SIZE(a) < 0)
- sign = '-';
+ assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND);
- if (Py_SIZE(a) == 0) {
+ p = PyUnicode_1BYTE_DATA(v) + sz;
+ if (size_a == 0) {
*--p = '0';
}
else {
/* JRH: special case for power-of-2 bases */
twodigits accum = 0;
int accumbits = 0; /* # of bits in accum */
+ Py_ssize_t i;
for (i = 0; i < size_a; ++i) {
accum |= (twodigits)a->ob_digit[i] << accumbits;
accumbits += PyLong_SHIFT;
@@ -1739,7 +1744,6 @@ _PyLong_Format(PyObject *aa, int base)
char cdigit;
cdigit = (char)(accum & (base - 1));
cdigit += (cdigit < 10) ? '0' : 'a'-10;
- assert(p > buffer);
*--p = cdigit;
accumbits -= bits;
accum >>= bits;
@@ -1754,10 +1758,9 @@ _PyLong_Format(PyObject *aa, int base)
else /* (base == 2) */
*--p = 'b';
*--p = '0';
- if (sign)
- *--p = sign;
- v = PyUnicode_DecodeASCII(p, &buffer[sz] - p, NULL);
- PyMem_Free(buffer);
+ if (negative)
+ *--p = '-';
+ assert(p == PyUnicode_1BYTE_DATA(v));
return v;
}