Skip to content

gh-155733: Validate keyword argument keys in operator.methodcaller and functools.partial - #155779

Open
pranavchoudhary-tech wants to merge 5 commits into
python:mainfrom
pranavchoudhary-tech:fix-nonstring-kwargs-155733
Open

gh-155733: Validate keyword argument keys in operator.methodcaller and functools.partial#155779
pranavchoudhary-tech wants to merge 5 commits into
python:mainfrom
pranavchoudhary-tech:fix-nonstring-kwargs-155733

Conversation

@pranavchoudhary-tech

Copy link
Copy Markdown
Contributor

gh-155733: Validate keyword argument keys in operator.methodcaller and functools.partial

Summary

Fixes gh-155733.

Previously, passing non-string keys as **kwargs into operator.methodcaller or functools.partial bypassed kwarg type validation, leading to vectorcall assertion failures (PyUnicode_Check) or segmentation faults in CPython.

This PR adds keyword type checks (PyUnicode_Check) to methodcaller_new, partial_new, and partial_vectorcall, raising TypeError: keywords must be strings cleanly.

@brijkapadia

Copy link
Copy Markdown
Contributor

I think there are some cases that you are missing (like __setstate__). Could you add what is in gh-145960 but not in this PR?

@pranavchoudhary-tech

Copy link
Copy Markdown
Contributor Author

@brijkapadia Good point. I've added string key validation to partial_setstate in C and setstate in functools.py, updated test_non_string_keywords to cover setstate, and rebased with main.

@@ -0,0 +1 @@
Validate keyword argument keys in ``operator.methodcaller`` and ``functools.partial`` to raise ``TypeError`` instead of crashing when non-string keys are passed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nitpick:

Suggested change
Validate keyword argument keys in ``operator.methodcaller`` and ``functools.partial`` to raise ``TypeError`` instead of crashing when non-string keys are passed.
Validate keyword arguments to :func:`operator.methodcaller` and :func:`functools.partial` to raise a :exc:`TypeError` instead of crashing with non-string keys.

* Note, tail is already coppied. */
Py_ssize_t pos = 0, i = 0;
PyObject *keyword_dict = n_merges ? pto_kw_merged : partial_keywords;
int valid_keys = 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also set valid_keys = 0 here instead (and update other occurrences to valid_keys). It doesn't really matter, but this is more consistent with other places. Maybe rename to something like error too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we should do it. It's more likely to have valid keys than not so it's less likely to hit error paths. As for renaming to error it's too broad. However, I would rename it to valid_kwargs

Comment on lines -503 to -504
/* Copy pto_keywords with overlapping call keywords merged
* Note, tail is already coppied. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we can remove this comment?

Comment thread Lib/functools.py
Comment on lines +420 to +421
if kwds is not None and any(not isinstance(k, str) for k in kwds):
raise TypeError("keywords must be strings")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you really need this check. You'll get the error when calling the function anyway. For instance, we don't check that Placeholder isn't passed as a keyword value either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segfault & Debug abort when functools.partial/operator.methodcaller keywords contains non-string keys

3 participants