From 588b3e5969a6992666c19fe390664efbb26ee8cf Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 9 Oct 2023 12:24:15 +0300 Subject: [PATCH 1/4] gh-110525: Cover `PySet_Add` corner case with `frozenset` objects --- Modules/_testcapi/set.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Modules/_testcapi/set.c b/Modules/_testcapi/set.c index f68a1859698132..a0c6b6a605dc3a 100644 --- a/Modules/_testcapi/set.c +++ b/Modules/_testcapi/set.c @@ -129,6 +129,33 @@ set_clear(PyObject *self, PyObject *obj) RETURN_INT(PySet_Clear(obj)); } +static PyObject * +test_frozenset_add_in_capi(PyObject *self, PyObject *Py_UNUSED(obj)) +{ + // Test that `frozenset` can be used with `PySet_Add`, + // when frozenset is just created in CAPI. + PyObject *fs = PyFrozenSet_New(NULL); + if (fs == NULL) { + return NULL; + } + PyObject *num = PyLong_FromLong(1); + if (num == NULL) { + return NULL; + } + if (PySet_Add(fs, num) < 0) { + return NULL; + } + int contains = PySet_Contains(fs, num); + if (contains < 0) { + return NULL; + } + else if (contains == 0) { + PyErr_SetString(PyExc_ValueError, "set does not contain expected value"); + return NULL; + } + Py_RETURN_NONE; +} + static PyMethodDef test_methods[] = { {"set_check", set_check, METH_O}, {"set_checkexact", set_checkexact, METH_O}, @@ -148,6 +175,8 @@ static PyMethodDef test_methods[] = { {"set_pop", set_pop, METH_O}, {"set_clear", set_clear, METH_O}, + {"test_frozenset_add_in_capi", test_frozenset_add_in_capi, METH_NOARGS}, + {NULL}, }; From 95f9ec759590660c69ed0430104d26a9e9d0b605 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 9 Oct 2023 13:13:39 +0300 Subject: [PATCH 2/4] Fix leak --- Modules/_testcapi/set.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_testcapi/set.c b/Modules/_testcapi/set.c index a0c6b6a605dc3a..8cfdc65325a320 100644 --- a/Modules/_testcapi/set.c +++ b/Modules/_testcapi/set.c @@ -146,6 +146,7 @@ test_frozenset_add_in_capi(PyObject *self, PyObject *Py_UNUSED(obj)) return NULL; } int contains = PySet_Contains(fs, num); + Py_DECREF(num); if (contains < 0) { return NULL; } From 4235ee8879cdb1581f06c63c1929c52bcfcde913 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 9 Oct 2023 13:28:22 +0300 Subject: [PATCH 3/4] Longer version --- Modules/_testcapi/set.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Modules/_testcapi/set.c b/Modules/_testcapi/set.c index 8cfdc65325a320..4ba113f56b4cb1 100644 --- a/Modules/_testcapi/set.c +++ b/Modules/_testcapi/set.c @@ -140,21 +140,26 @@ test_frozenset_add_in_capi(PyObject *self, PyObject *Py_UNUSED(obj)) } PyObject *num = PyLong_FromLong(1); if (num == NULL) { - return NULL; + goto error; } if (PySet_Add(fs, num) < 0) { - return NULL; + goto error; } int contains = PySet_Contains(fs, num); - Py_DECREF(num); if (contains < 0) { - return NULL; + goto error; } else if (contains == 0) { - PyErr_SetString(PyExc_ValueError, "set does not contain expected value"); - return NULL; + goto unexpected; } Py_RETURN_NONE; + +unexpected: + PyErr_SetString(PyExc_ValueError, "set does not contain expected value"); +error: + Py_DECREF(fs); + Py_XDECREF(num); + return NULL; } static PyMethodDef test_methods[] = { From 7d9ae7a6628428370781e86ff0149cbd2edb9065 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 9 Oct 2023 13:30:51 +0300 Subject: [PATCH 4/4] Longer version --- Modules/_testcapi/set.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_testcapi/set.c b/Modules/_testcapi/set.c index 4ba113f56b4cb1..3c58f185638c75 100644 --- a/Modules/_testcapi/set.c +++ b/Modules/_testcapi/set.c @@ -152,6 +152,8 @@ test_frozenset_add_in_capi(PyObject *self, PyObject *Py_UNUSED(obj)) else if (contains == 0) { goto unexpected; } + Py_DECREF(fs); + Py_DECREF(num); Py_RETURN_NONE; unexpected: