From b781ae747f65faa8ebf6d1f07922aa21585eae81 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 2 Jan 2025 15:00:31 +0100 Subject: [PATCH 1/2] Refactor to avoid incref/decref --- Python/getargs.c | 55 ++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c index 0865e335f90a62..e21ea0592e42f6 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -437,6 +437,27 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, } +static const char * +convertitems(PyObject *arg, const char **p_format, va_list *p_va, int flags, + int *levels, char *msgbuf, size_t bufsize, + freelist_t *freelist) +{ + const char *format = *p_format; + int n = PyTuple_GET_SIZE(arg); + for (int i = 0; i < n; i++) { + PyObject *item = PyTuple_GET_ITEM(arg, i); + const char *msg = convertitem(item, &format, p_va, flags, levels+1, + msgbuf, bufsize, freelist); + if (msg != NULL) { + levels[0] = i+1; + return msg; + } + } + *p_format = format; + return NULL; +} + + /* Convert a tuple argument. On entry, *p_format points to the character _after_ the opening '('. On successful exit, *p_format points to the closing ')'. @@ -463,7 +484,6 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int level = 0; int n = 0; const char *format = *p_format; - int i; Py_ssize_t len; int mustbetuple = PyTuple_Check(arg); @@ -512,10 +532,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } } - if (PyTuple_Check(arg)) { - Py_INCREF(arg); - } - else if (!PySequence_Check(arg) || + if (!PySequence_Check(arg) || PyUnicode_Check(arg) || PyBytes_Check(arg) || PyByteArray_Check(arg)) { levels[0] = 0; @@ -525,7 +542,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); return msgbuf; } - else { + else if (!PyTuple_Check(arg)) { if (mustbetuple) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 0, "argument must be %d-item tuple, not %T", n, arg)) @@ -541,10 +558,13 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, mustbetuple ? "tuple" : "sequence", n, len); return msgbuf; } - arg = PySequence_Tuple(arg); - if (arg == NULL) { + PyObject *tuple = PySequence_Tuple(arg); + if (tuple == NULL) { return msgbuf; } + + return convertitems(tuple, p_format, p_va, flags, levels, + msgbuf, bufsize, freelist); } len = PyTuple_GET_SIZE(arg); @@ -553,26 +573,11 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyOS_snprintf(msgbuf, bufsize, "must be tuple of length %d, not %zd", n, len); - Py_DECREF(arg); return msgbuf; } - format = *p_format; - for (i = 0; i < n; i++) { - const char *msg; - PyObject *item = PyTuple_GET_ITEM(arg, i); - msg = convertitem(item, &format, p_va, flags, levels+1, - msgbuf, bufsize, freelist); - if (msg != NULL) { - levels[0] = i+1; - Py_DECREF(arg); - return msg; - } - } - - *p_format = format; - Py_DECREF(arg); - return NULL; + return convertitems(arg, p_format, p_va, flags, levels, + msgbuf, bufsize, freelist); } From 6374772a8f0af1121e397188fca129357cf252f3 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 2 Jan 2025 21:06:21 +0100 Subject: [PATCH 2/2] Address review --- Python/getargs.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c index e21ea0592e42f6..8148989c36ad21 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -438,9 +438,9 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, static const char * -convertitems(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, - freelist_t *freelist) +converttupleitems(PyObject *arg, const char **p_format, va_list *p_va, + int flags, int *levels, char *msgbuf, size_t bufsize, + freelist_t *freelist) { const char *format = *p_format; int n = PyTuple_GET_SIZE(arg); @@ -532,7 +532,10 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } } - if (!PySequence_Check(arg) || + if (PyTuple_Check(arg)) { + // Pass. + } + else if (!PySequence_Check(arg) || PyUnicode_Check(arg) || PyBytes_Check(arg) || PyByteArray_Check(arg)) { levels[0] = 0; @@ -542,7 +545,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); return msgbuf; } - else if (!PyTuple_Check(arg)) { + else { if (mustbetuple) { if (PyErr_WarnFormat(PyExc_DeprecationWarning, 0, "argument must be %d-item tuple, not %T", n, arg)) @@ -563,8 +566,10 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return msgbuf; } - return convertitems(tuple, p_format, p_va, flags, levels, - msgbuf, bufsize, freelist); + const char *ret = converttupleitems(tuple, p_format, p_va, flags, + levels, msgbuf, bufsize, freelist); + Py_DECREF(tuple); + return ret; } len = PyTuple_GET_SIZE(arg); @@ -576,8 +581,8 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return msgbuf; } - return convertitems(arg, p_format, p_va, flags, levels, - msgbuf, bufsize, freelist); + return converttupleitems(arg, p_format, p_va, flags, levels, + msgbuf, bufsize, freelist); }