Skip to content

Commit f2387da

Browse files
committed
Merged revisions 78420 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r78420 | eric.smith | 2010-02-24 10:42:29 -0500 (Wed, 24 Feb 2010) | 9 lines Merged revisions 78418 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78418 | eric.smith | 2010-02-24 09:15:36 -0500 (Wed, 24 Feb 2010) | 1 line Issue #7309: Unchecked pointer access when converting UnicodeEncodeError, UnicodeDecodeError, and UnicodeTranslateError to strings. ........ ................
1 parent b61a04d commit f2387da

3 files changed

Lines changed: 119 additions & 34 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,42 @@ def __del__(self):
568568
pass
569569
self.assertEquals(e, (None, None, None))
570570

571+
def testUnicodeChangeAttributes(self):
572+
# See issue 7309. This was a crasher.
573+
574+
u = UnicodeEncodeError('baz', 'xxxxx', 1, 5, 'foo')
575+
self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo")
576+
u.end = 2
577+
self.assertEqual(str(u), "'baz' codec can't encode character '\\x78' in position 1: foo")
578+
u.end = 5
579+
u.reason = 0x345345345345345345
580+
self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
581+
u.encoding = 4000
582+
self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
583+
u.start = 1000
584+
self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")
585+
586+
u = UnicodeDecodeError('baz', b'xxxxx', 1, 5, 'foo')
587+
self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo")
588+
u.end = 2
589+
self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo")
590+
u.end = 5
591+
u.reason = 0x345345345345345345
592+
self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
593+
u.encoding = 4000
594+
self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
595+
u.start = 1000
596+
self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")
597+
598+
u = UnicodeTranslateError('xxxx', 1, 5, 'foo')
599+
self.assertEqual(str(u), "can't translate characters in position 1-4: foo")
600+
u.end = 2
601+
self.assertEqual(str(u), "can't translate character '\\x78' in position 1: foo")
602+
u.end = 5
603+
u.reason = 0x345345345345345345
604+
self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997")
605+
u.start = 1000
606+
self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")
571607

572608
def test_badisinstance(self):
573609
# Bug #2542: if issubclass(e, MyException) raises an exception,

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Core and Builtins
1313
-----------------
1414

1515
=======
16+
- Issue #7309: Fix unchecked attribute access when converting
17+
UnicodeEncodeError, UnicodeDecodeError, and UnicodeTranslateError to
18+
strings.
19+
1620
- Issue #6902: Fix problem with built-in types format incorrectly with
1721
0 padding.
1822

Objects/exceptions.c

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,8 +1434,20 @@ static PyObject *
14341434
UnicodeEncodeError_str(PyObject *self)
14351435
{
14361436
PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1437-
1438-
if (uself->end==uself->start+1) {
1437+
PyObject *result = NULL;
1438+
PyObject *reason_str = NULL;
1439+
PyObject *encoding_str = NULL;
1440+
1441+
/* Get reason and encoding as strings, which they might not be if
1442+
they've been modified after we were contructed. */
1443+
reason_str = PyObject_Str(uself->reason);
1444+
if (reason_str == NULL)
1445+
goto done;
1446+
encoding_str = PyObject_Str(uself->encoding);
1447+
if (encoding_str == NULL)
1448+
goto done;
1449+
1450+
if (uself->start < PyUnicode_GET_SIZE(uself->object) && uself->end == uself->start+1) {
14391451
int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];
14401452
const char *fmt;
14411453
if (badchar <= 0xff)
@@ -1444,21 +1456,25 @@ UnicodeEncodeError_str(PyObject *self)
14441456
fmt = "'%U' codec can't encode character '\\u%04x' in position %zd: %U";
14451457
else
14461458
fmt = "'%U' codec can't encode character '\\U%08x' in position %zd: %U";
1447-
return PyUnicode_FromFormat(
1459+
result = PyUnicode_FromFormat(
14481460
fmt,
1449-
((PyUnicodeErrorObject *)self)->encoding,
1461+
encoding_str,
14501462
badchar,
14511463
uself->start,
1452-
((PyUnicodeErrorObject *)self)->reason
1453-
);
1464+
reason_str);
14541465
}
1455-
return PyUnicode_FromFormat(
1456-
"'%U' codec can't encode characters in position %zd-%zd: %U",
1457-
((PyUnicodeErrorObject *)self)->encoding,
1458-
uself->start,
1459-
uself->end-1,
1460-
((PyUnicodeErrorObject *)self)->reason
1461-
);
1466+
else {
1467+
result = PyUnicode_FromFormat(
1468+
"'%U' codec can't encode characters in position %zd-%zd: %U",
1469+
encoding_str,
1470+
uself->start,
1471+
uself->end-1,
1472+
reason_str);
1473+
}
1474+
done:
1475+
Py_XDECREF(reason_str);
1476+
Py_XDECREF(encoding_str);
1477+
return result;
14621478
}
14631479

14641480
static PyTypeObject _PyExc_UnicodeEncodeError = {
@@ -1536,24 +1552,41 @@ static PyObject *
15361552
UnicodeDecodeError_str(PyObject *self)
15371553
{
15381554
PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1539-
1540-
if (uself->end==uself->start+1) {
1555+
PyObject *result = NULL;
1556+
PyObject *reason_str = NULL;
1557+
PyObject *encoding_str = NULL;
1558+
1559+
/* Get reason and encoding as strings, which they might not be if
1560+
they've been modified after we were contructed. */
1561+
reason_str = PyObject_Str(uself->reason);
1562+
if (reason_str == NULL)
1563+
goto done;
1564+
encoding_str = PyObject_Str(uself->encoding);
1565+
if (encoding_str == NULL)
1566+
goto done;
1567+
1568+
if (uself->start < PyBytes_GET_SIZE(uself->object) && uself->end == uself->start+1) {
15411569
int byte = (int)(PyBytes_AS_STRING(((PyUnicodeErrorObject *)self)->object)[uself->start]&0xff);
1542-
return PyUnicode_FromFormat(
1570+
result = PyUnicode_FromFormat(
15431571
"'%U' codec can't decode byte 0x%02x in position %zd: %U",
1544-
((PyUnicodeErrorObject *)self)->encoding,
1572+
encoding_str,
15451573
byte,
15461574
uself->start,
1547-
((PyUnicodeErrorObject *)self)->reason
1548-
);
1575+
reason_str);
15491576
}
1550-
return PyUnicode_FromFormat(
1551-
"'%U' codec can't decode bytes in position %zd-%zd: %U",
1552-
((PyUnicodeErrorObject *)self)->encoding,
1553-
uself->start,
1554-
uself->end-1,
1555-
((PyUnicodeErrorObject *)self)->reason
1556-
);
1577+
else {
1578+
result = PyUnicode_FromFormat(
1579+
"'%U' codec can't decode bytes in position %zd-%zd: %U",
1580+
encoding_str,
1581+
uself->start,
1582+
uself->end-1,
1583+
reason_str
1584+
);
1585+
}
1586+
done:
1587+
Py_XDECREF(reason_str);
1588+
Py_XDECREF(encoding_str);
1589+
return result;
15571590
}
15581591

15591592
static PyTypeObject _PyExc_UnicodeDecodeError = {
@@ -1617,8 +1650,16 @@ static PyObject *
16171650
UnicodeTranslateError_str(PyObject *self)
16181651
{
16191652
PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
1653+
PyObject *result = NULL;
1654+
PyObject *reason_str = NULL;
16201655

1621-
if (uself->end==uself->start+1) {
1656+
/* Get reason as a string, which it might not be if it's been
1657+
modified after we were contructed. */
1658+
reason_str = PyObject_Str(uself->reason);
1659+
if (reason_str == NULL)
1660+
goto done;
1661+
1662+
if (uself->start < PyUnicode_GET_SIZE(uself->object) && uself->end == uself->start+1) {
16221663
int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];
16231664
const char *fmt;
16241665
if (badchar <= 0xff)
@@ -1631,15 +1672,19 @@ UnicodeTranslateError_str(PyObject *self)
16311672
fmt,
16321673
badchar,
16331674
uself->start,
1634-
uself->reason
1675+
reason_str
16351676
);
1677+
} else {
1678+
result = PyUnicode_FromFormat(
1679+
"can't translate characters in position %zd-%zd: %U",
1680+
uself->start,
1681+
uself->end-1,
1682+
reason_str
1683+
);
16361684
}
1637-
return PyUnicode_FromFormat(
1638-
"can't translate characters in position %zd-%zd: %U",
1639-
uself->start,
1640-
uself->end-1,
1641-
uself->reason
1642-
);
1685+
done:
1686+
Py_XDECREF(reason_str);
1687+
return result;
16431688
}
16441689

16451690
static PyTypeObject _PyExc_UnicodeTranslateError = {

0 commit comments

Comments
 (0)