python / python/cpython

Python pickle `load_reduce` function doesn't check if `args` is a tuple

Open
#144,412 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

extension-modules type-bug
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Bug report

Bug description:

When load_reduce() is called in Python pickle, the args variable is pulled off the stack and passed into the functions using the * operator. This syntax is type-permissive, meaning the type can be any iterable that will return the needed arguments.

https://github.com/python/cpython/blob/29acc08c8dad664cd5713cb392e5beba65724c10/Lib/pickle.py#L1723-L1727

However, in C _pickle, argtup is pulled off the stack and passed into PyObject_CallObject(), which checks if the args parameter is specifically a PyTuple().

https://github.com/python/cpython/blob/29acc08c8dad664cd5713cb392e5beba65724c10/Modules/_pickle.c#L6964

https://github.com/python/cpython/blob/29acc08c8dad664cd5713cb392e5beba65724c10/Objects/call.c#L460-L473

This means that any non-tuple iterator being used as the arguments passed into the function will cause C _pickle to throw an error, but Python pickle deserialization to unfold just fine.

payload:      b'cbuiltins\nprint\n}R.'

pickle:
None
_pickle.c:    FAILURE argument list must be a tuple
pickletools:
    0: c    GLOBAL     'builtins print'
   16: }    EMPTY_DICT
   17: R    REDUCE
   18: .    STOP
highest protocol among opcodes = 1

I think the easiest way to remedy the discrepancy is to explicitly type check the args parameter in pickle.py's load_reduce() function.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-144419

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Lib/pickle.py's load_reduce() and compare its argument handling with Modules/_pickle.c and the PyObject_CallObject() behavior referenced in Objects/call.c. Check the linked PR gh-144419 and the existing pickle tests; done means Python pickle and _pickle handle the reported non-tuple argument case consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.