Issue #25019: Fixed a crash caused by setting non-string key of expat parser.

Added additional tests for expat parser attributes.
Based on patch by John Leitch.
This commit is contained in:
Serhiy Storchaka 2015-09-07 22:41:04 +03:00
commit 9df7035f5b
4 changed files with 51 additions and 16 deletions

View File

@ -16,22 +16,47 @@ from test.support import sortdict
class SetAttributeTest(unittest.TestCase): class SetAttributeTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.parser = expat.ParserCreate(namespace_separator='!') self.parser = expat.ParserCreate(namespace_separator='!')
self.set_get_pairs = [
[0, 0], def test_buffer_text(self):
[1, 1], self.assertIs(self.parser.buffer_text, False)
[2, 1], for x in 0, 1, 2, 0:
[0, 0], self.parser.buffer_text = x
] self.assertIs(self.parser.buffer_text, bool(x))
def test_namespace_prefixes(self):
self.assertIs(self.parser.namespace_prefixes, False)
for x in 0, 1, 2, 0:
self.parser.namespace_prefixes = x
self.assertIs(self.parser.namespace_prefixes, bool(x))
def test_ordered_attributes(self): def test_ordered_attributes(self):
for x, y in self.set_get_pairs: self.assertIs(self.parser.ordered_attributes, False)
for x in 0, 1, 2, 0:
self.parser.ordered_attributes = x self.parser.ordered_attributes = x
self.assertEqual(self.parser.ordered_attributes, y) self.assertIs(self.parser.ordered_attributes, bool(x))
def test_specified_attributes(self): def test_specified_attributes(self):
for x, y in self.set_get_pairs: self.assertIs(self.parser.specified_attributes, False)
for x in 0, 1, 2, 0:
self.parser.specified_attributes = x self.parser.specified_attributes = x
self.assertEqual(self.parser.specified_attributes, y) self.assertIs(self.parser.specified_attributes, bool(x))
def test_specified_attributes(self):
self.assertIs(self.parser.specified_attributes, False)
for x in 0, 1, 2, 0:
self.parser.specified_attributes = x
self.assertIs(self.parser.specified_attributes, bool(x))
def test_invalid_attributes(self):
with self.assertRaises(AttributeError):
self.parser.returns_unicode = 1
with self.assertRaises(AttributeError):
self.parser.returns_unicode
# Issue #25019
self.assertRaises(TypeError, setattr, self.parser, range(0xF), 0)
self.assertRaises(TypeError, self.parser.__setattr__, range(0xF), 0)
self.assertRaises(TypeError, getattr, self.parser, range(0xF))
data = b'''\ data = b'''\
@ -514,11 +539,12 @@ class ChardataBufferTest(unittest.TestCase):
def test_wrong_size(self): def test_wrong_size(self):
parser = expat.ParserCreate() parser = expat.ParserCreate()
parser.buffer_text = 1 parser.buffer_text = 1
def f(size): with self.assertRaises(ValueError):
parser.buffer_size = size parser.buffer_size = -1
with self.assertRaises(ValueError):
self.assertRaises(ValueError, f, -1) parser.buffer_size = 0
self.assertRaises(ValueError, f, 0) with self.assertRaises(TypeError):
parser.buffer_size = 512.0
def test_unchanged_size(self): def test_unchanged_size(self):
xml1 = b"<?xml version='1.0' encoding='iso8859'?><s>" + b'a' * 512 xml1 = b"<?xml version='1.0' encoding='iso8859'?><s>" + b'a' * 512

View File

@ -831,6 +831,7 @@ Joerg Lehmann
Robert Lehmann Robert Lehmann
Petri Lehtinen Petri Lehtinen
Luke Kenneth Casson Leighton Luke Kenneth Casson Leighton
John Leitch
Tshepang Lekhonkhobe Tshepang Lekhonkhobe
Marc-André Lemburg Marc-André Lemburg
Mateusz Lenik Mateusz Lenik

View File

@ -103,6 +103,9 @@ Core and Builtins
Library Library
------- -------
- Issue #25019: Fixed a crash caused by setting non-string key of expat parser.
Based on patch by John Leitch.
- Issue #16180: Exit pdb if file has syntax error, instead of trapping user - Issue #16180: Exit pdb if file has syntax error, instead of trapping user
in an infinite loop. Patch by Xavier de Gaye. in an infinite loop. Patch by Xavier de Gaye.

View File

@ -1378,11 +1378,16 @@ static int
xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v) xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v)
{ {
/* Set attribute 'name' to value 'v'. v==NULL means delete */ /* Set attribute 'name' to value 'v'. v==NULL means delete */
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
name->ob_type->tp_name);
return -1;
}
if (v == NULL) { if (v == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
return -1; return -1;
} }
assert(PyUnicode_Check(name));
if (PyUnicode_CompareWithASCIIString(name, "buffer_text") == 0) { if (PyUnicode_CompareWithASCIIString(name, "buffer_text") == 0) {
int b = PyObject_IsTrue(v); int b = PyObject_IsTrue(v);
if (b < 0) if (b < 0)