Commit 5d5296d3 authored by Brett Cannon's avatar Brett Cannon

Merge

parents bbdc9cd3 9a359bd9
...@@ -1228,6 +1228,20 @@ class LongTest(unittest.TestCase): ...@@ -1228,6 +1228,20 @@ class LongTest(unittest.TestCase):
self.assertRaises(TypeError, myint.from_bytes, 0, 'big') self.assertRaises(TypeError, myint.from_bytes, 0, 'big')
self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) 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(): def test_main():
support.run_unittest(LongTest) support.run_unittest(LongTest)
......
...@@ -10,6 +10,12 @@ What's New in Python 3.3.0 Alpha 3? ...@@ -10,6 +10,12 @@ What's New in Python 3.3.0 Alpha 3?
Core and Builtins 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. - Issue #14098: New functions PyErr_GetExcInfo and PyErr_SetExcInfo.
Patch by Stefan Behnel. Patch by Stefan Behnel.
......
...@@ -156,9 +156,7 @@ _PyLong_Copy(PyLongObject *src) ...@@ -156,9 +156,7 @@ _PyLong_Copy(PyLongObject *src)
if (i < 0) if (i < 0)
i = -(i); i = -(i);
if (i < 2) { if (i < 2) {
sdigit ival = src->ob_digit[0]; sdigit ival = MEDIUM_VALUE(src);
if (Py_SIZE(src) < 0)
ival = -ival;
CHECK_SMALL_INT(ival); CHECK_SMALL_INT(ival);
} }
result = _PyLong_New(i); result = _PyLong_New(i);
...@@ -1672,11 +1670,10 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1672,11 +1670,10 @@ _PyLong_Format(PyObject *aa, int base)
{ {
register PyLongObject *a = (PyLongObject *)aa; register PyLongObject *a = (PyLongObject *)aa;
PyObject *v; PyObject *v;
Py_ssize_t i, sz; Py_ssize_t sz;
Py_ssize_t size_a; Py_ssize_t size_a;
char *p; Py_UCS1 *p;
char sign = '\0'; int negative;
char *buffer;
int bits; int bits;
assert(base == 2 || base == 8 || base == 10 || base == 16); assert(base == 2 || base == 8 || base == 10 || base == 16);
...@@ -1688,6 +1685,7 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1688,6 +1685,7 @@ _PyLong_Format(PyObject *aa, int base)
return NULL; return NULL;
} }
size_a = ABS(Py_SIZE(a)); size_a = ABS(Py_SIZE(a));
negative = Py_SIZE(a) < 0;
/* Compute a rough upper bound for the length of the string */ /* Compute a rough upper bound for the length of the string */
switch (base) { switch (base) {
...@@ -1704,33 +1702,40 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1704,33 +1702,40 @@ _PyLong_Format(PyObject *aa, int base)
assert(0); /* shouldn't ever get here */ assert(0); /* shouldn't ever get here */
bits = 0; /* to silence gcc warning */ bits = 0; /* to silence gcc warning */
} }
/* compute length of output string: allow 2 characters for prefix and
1 for possible '-' sign. */ /* Compute exact length 'sz' of output string. */
if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT / sizeof(Py_UCS4)) { if (size_a == 0) {
sz = 3;
}
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, PyErr_SetString(PyExc_OverflowError,
"int is too large to format"); "int is too large to format");
return NULL; return NULL;
} }
/* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below size_a_in_bits = (size_a - 1) * PyLong_SHIFT +
is safe from overflow */ bits_in_digit(a->ob_digit[size_a - 1]);
sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits; /* Allow 2 characters for prefix and 1 for a '-' sign. */
assert(sz >= 0); sz = 2 + negative + (size_a_in_bits + (bits - 1)) / bits;
buffer = PyMem_Malloc(sz); }
if (buffer == NULL) {
PyErr_NoMemory(); v = PyUnicode_New(sz, 'x');
if (v == NULL) {
return NULL; return NULL;
} }
p = &buffer[sz]; assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND);
if (Py_SIZE(a) < 0)
sign = '-';
if (Py_SIZE(a) == 0) { p = PyUnicode_1BYTE_DATA(v) + sz;
if (size_a == 0) {
*--p = '0'; *--p = '0';
} }
else { else {
/* JRH: special case for power-of-2 bases */ /* JRH: special case for power-of-2 bases */
twodigits accum = 0; twodigits accum = 0;
int accumbits = 0; /* # of bits in accum */ int accumbits = 0; /* # of bits in accum */
Py_ssize_t i;
for (i = 0; i < size_a; ++i) { for (i = 0; i < size_a; ++i) {
accum |= (twodigits)a->ob_digit[i] << accumbits; accum |= (twodigits)a->ob_digit[i] << accumbits;
accumbits += PyLong_SHIFT; accumbits += PyLong_SHIFT;
...@@ -1739,7 +1744,6 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1739,7 +1744,6 @@ _PyLong_Format(PyObject *aa, int base)
char cdigit; char cdigit;
cdigit = (char)(accum & (base - 1)); cdigit = (char)(accum & (base - 1));
cdigit += (cdigit < 10) ? '0' : 'a'-10; cdigit += (cdigit < 10) ? '0' : 'a'-10;
assert(p > buffer);
*--p = cdigit; *--p = cdigit;
accumbits -= bits; accumbits -= bits;
accum >>= bits; accum >>= bits;
...@@ -1754,10 +1758,9 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1754,10 +1758,9 @@ _PyLong_Format(PyObject *aa, int base)
else /* (base == 2) */ else /* (base == 2) */
*--p = 'b'; *--p = 'b';
*--p = '0'; *--p = '0';
if (sign) if (negative)
*--p = sign; *--p = '-';
v = PyUnicode_DecodeASCII(p, &buffer[sz] - p, NULL); assert(p == PyUnicode_1BYTE_DATA(v));
PyMem_Free(buffer);
return v; return v;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment