summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-09-06 19:47:38 (GMT)
committerGitHub <noreply@github.com>2023-09-06 19:47:38 (GMT)
commit3a08db8d137a552aebf678bcd2e7444ab72e62c5 (patch)
treed256c8449e9c8576c965f1c8f0cf4f2ac109f4d1
parentbf414b7fcb7c8ba780a5e1d9f320ecef0c7f9488 (diff)
downloadcpython-3a08db8d137a552aebf678bcd2e7444ab72e62c5.zip
cpython-3a08db8d137a552aebf678bcd2e7444ab72e62c5.tar.gz
cpython-3a08db8d137a552aebf678bcd2e7444ab72e62c5.tar.bz2
gh-106307: Fix PyMapping_GetOptionalItemString() (GH-108797)
The resulting pointer was not set to NULL if the creation of a temporary string object was failed. The tests were also missed due to oversight.
-rw-r--r--Lib/test/test_capi/test_abstract.py37
-rw-r--r--Objects/abstract.c2
2 files changed, 39 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_abstract.py b/Lib/test/test_capi/test_abstract.py
index 3f51e5b..671f62b 100644
--- a/Lib/test/test_capi/test_abstract.py
+++ b/Lib/test/test_capi/test_abstract.py
@@ -265,6 +265,43 @@ class CAPITest(unittest.TestCase):
self.assertRaises(TypeError, getitemstring, [], b'a')
self.assertRaises(SystemError, getitemstring, NULL, b'a')
+ def test_mapping_getoptionalitem(self):
+ getitem = _testcapi.mapping_getoptionalitem
+ dct = {'a': 1, '\U0001f40d': 2}
+ self.assertEqual(getitem(dct, 'a'), 1)
+ self.assertEqual(getitem(dct, 'b'), KeyError)
+ self.assertEqual(getitem(dct, '\U0001f40d'), 2)
+
+ dct2 = ProxyGetItem(dct)
+ self.assertEqual(getitem(dct2, 'a'), 1)
+ self.assertEqual(getitem(dct2, 'b'), KeyError)
+
+ self.assertEqual(getitem(['a', 'b', 'c'], 1), 'b')
+
+ self.assertRaises(TypeError, getitem, 42, 'a')
+ self.assertRaises(TypeError, getitem, {}, []) # unhashable
+ self.assertRaises(IndexError, getitem, [], 1)
+ self.assertRaises(TypeError, getitem, [], 'a')
+ # CRASHES getitem({}, NULL)
+ # CRASHES getitem(NULL, 'a')
+
+ def test_mapping_getoptionalitemstring(self):
+ getitemstring = _testcapi.mapping_getoptionalitemstring
+ dct = {'a': 1, '\U0001f40d': 2}
+ self.assertEqual(getitemstring(dct, b'a'), 1)
+ self.assertEqual(getitemstring(dct, b'b'), KeyError)
+ self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)
+
+ dct2 = ProxyGetItem(dct)
+ self.assertEqual(getitemstring(dct2, b'a'), 1)
+ self.assertEqual(getitemstring(dct2, b'b'), KeyError)
+
+ self.assertRaises(TypeError, getitemstring, 42, b'a')
+ self.assertRaises(UnicodeDecodeError, getitemstring, {}, b'\xff')
+ self.assertRaises(SystemError, getitemstring, {}, NULL)
+ self.assertRaises(TypeError, getitemstring, [], b'a')
+ # CRASHES getitemstring(NULL, b'a')
+
def test_mapping_haskey(self):
haskey = _testcapi.mapping_haskey
dct = {'a': 1, '\U0001f40d': 2}
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 6713926..b57190d 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2393,11 +2393,13 @@ int
PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
{
if (key == NULL) {
+ *result = NULL;
null_error();
return -1;
}
PyObject *okey = PyUnicode_FromString(key);
if (okey == NULL) {
+ *result = NULL;
return -1;
}
int rc = PyMapping_GetOptionalItem(obj, okey, result);