From 7fbe986a1757b960ffd0bd2d39ddc5ff9cb132c9 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 5 Jan 2022 10:16:25 +0900 Subject: [PATCH 1/4] bpo-46236: Fix PyFunction_GetAnnotations() returned tuple. --- .../next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst | 2 ++ Objects/funcobject.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst diff --git a/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst new file mode 100644 index 00000000000000..d8914662600cbc --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst @@ -0,0 +1,2 @@ +Fix :c:func:`PyFunction_GetAnnotations` might return a tuple instead of a +dict. diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 7891e4f3122b15..29fb66bf3e4987 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -281,7 +281,11 @@ PyFunction_GetAnnotations(PyObject *op) PyErr_BadInternalCall(); return NULL; } - return ((PyFunctionObject *) op) -> func_annotations; + PyObject *func = (PyFunctionObject *)op; + if (func->func_annotations == NULL) { + return NULL; + } + return func_get_annotations(op, NULL); } int From a41b64ec19af82dcaa08629e1aac7222a93dcb4c Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 5 Jan 2022 10:31:19 +0900 Subject: [PATCH 2/4] fixup --- Objects/funcobject.c | 57 ++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 29fb66bf3e4987..9e3b01699bfd39 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -274,6 +274,35 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) return 0; } +static PyObject * +func_get_annotation_dict(PyFunctionObject *op) +{ + if (op->func_annotations == NULL) { + return NULL; + } + if (PyTuple_CheckExact(op->func_annotations)) { + PyObject *ann_tuple = op->func_annotations; + PyObject *ann_dict = PyDict_New(); + if (ann_dict == NULL) { + return NULL; + } + + assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0); + + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) { + int err = PyDict_SetItem(ann_dict, + PyTuple_GET_ITEM(ann_tuple, i), + PyTuple_GET_ITEM(ann_tuple, i + 1)); + + if (err < 0) + return NULL; + } + Py_SETREF(op->func_annotations, ann_dict); + } + Py_INCREF(op->func_annotations); + return op->func_annotations; +} + PyObject * PyFunction_GetAnnotations(PyObject *op) { @@ -281,11 +310,7 @@ PyFunction_GetAnnotations(PyObject *op) PyErr_BadInternalCall(); return NULL; } - PyObject *func = (PyFunctionObject *)op; - if (func->func_annotations == NULL) { - return NULL; - } - return func_get_annotations(op, NULL); + return func_get_annotation_dict((PyFunctionObject *)op); } int @@ -505,27 +530,7 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored)) if (op->func_annotations == NULL) return NULL; } - if (PyTuple_CheckExact(op->func_annotations)) { - PyObject *ann_tuple = op->func_annotations; - PyObject *ann_dict = PyDict_New(); - if (ann_dict == NULL) { - return NULL; - } - - assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0); - - for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) { - int err = PyDict_SetItem(ann_dict, - PyTuple_GET_ITEM(ann_tuple, i), - PyTuple_GET_ITEM(ann_tuple, i + 1)); - - if (err < 0) - return NULL; - } - Py_SETREF(op->func_annotations, ann_dict); - } - Py_INCREF(op->func_annotations); - return op->func_annotations; + return func_get_annotation_dict(op); } static int From 1a75c41170fb008757e2796acd51fb9fd0240699 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 5 Jan 2022 13:08:37 +0900 Subject: [PATCH 3/4] Add assertion --- Objects/funcobject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 9e3b01699bfd39..a8f006da8ad33f 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -294,12 +294,14 @@ func_get_annotation_dict(PyFunctionObject *op) PyTuple_GET_ITEM(ann_tuple, i), PyTuple_GET_ITEM(ann_tuple, i + 1)); - if (err < 0) + if (err < 0) { return NULL; + } } Py_SETREF(op->func_annotations, ann_dict); } Py_INCREF(op->func_annotations); + assert(PyDict_Check(op->func_annotations)); return op->func_annotations; } From 9bc2a72170ca5cd45ee7555ea8b8963965905067 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Wed, 5 Jan 2022 11:46:55 +0000 Subject: [PATCH 4/4] Update Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst --- .../NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst index d8914662600cbc..61906584a16a38 100644 --- a/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst +++ b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst @@ -1,2 +1 @@ -Fix :c:func:`PyFunction_GetAnnotations` might return a tuple instead of a -dict. +Fix a bug in :c:func:`PyFunction_GetAnnotations` that caused it to return a ``tuple`` instead of a ``dict``.