summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2017-04-20 21:19:31 +0300
committerGitHub <noreply@github.com>2017-04-20 21:19:31 +0300
commit40db90c1ce1a59d5f5f2894bb0ce32110000bf27 (patch)
tree0436658cf04e8ebd902a9bc1851b21ee7b98bf45
parent8f5cdfa9fc1bb6b4d9a33fc281987252f6398430 (diff)
downloadcpython-git-40db90c1ce1a59d5f5f2894bb0ce32110000bf27.tar.gz
bpo-29802: Fix reference counting in module-level struct functions (#1213)
when pass arguments of wrong type.
-rw-r--r--Lib/test/test_struct.py10
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_struct.c1
-rw-r--r--Objects/unicodeobject.c1
4 files changed, 15 insertions, 0 deletions
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index 932ef47378..02d50b2d1c 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -599,6 +599,16 @@ class StructTest(unittest.TestCase):
'offset -11 out of range for 10-byte buffer'):
struct.pack_into('<B', byte_list, -11, 123)
+ def test_issue29802(self):
+ # When the second argument of struct.unpack() was of wrong type
+ # the Struct object was decrefed twice and the reference to
+ # deallocated object was left in a cache.
+ with self.assertRaises(TypeError):
+ struct.unpack(b'b', 0)
+ # Shouldn't crash.
+ self.assertEqual(struct.unpack(b'b', b'a'), (b'a'[0],))
+
+
class UnpackIteratorTest(unittest.TestCase):
"""
Tests for iterative unpacking (struct.Struct.iter_unpack).
diff --git a/Misc/NEWS b/Misc/NEWS
index 7e09eff4e0..fe1b0f839d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -317,6 +317,9 @@ Extension Modules
Library
-------
+- bpo-29802: Fixed reference counting in module-level struct functions when
+ pass arguments of wrong type.
+
- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.
- bpo-22352: Column widths in the output of dis.dis() are now adjusted for
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 4bc4186923..a614be89d2 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -2083,6 +2083,7 @@ cache_struct_converter(PyObject *fmt, PyObject **ptr)
if (fmt == NULL) {
Py_DECREF(*ptr);
+ *ptr = NULL;
return 1;
}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index ef2215fbc3..b68042179f 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3907,6 +3907,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
PyObject *output = NULL;
if (arg == NULL) {
Py_DECREF(*(PyObject**)addr);
+ *(PyObject**)addr = NULL;
return 1;
}