Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork34k
Description
Bug report
Bug description:
Whenload_reduce() is called in Pythonpickle, theargs 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.
Lines 1723 to 1727 in29acc08
| defload_reduce(self): | |
| stack=self.stack | |
| args=stack.pop() | |
| func=stack[-1] | |
| stack[-1]=func(*args) |
However, in C_pickle,argtup is pulled off the stack and passed intoPyObject_CallObject(), which checks if theargs parameter is specifically aPyTuple().
Line 6964 in29acc08
| obj=PyObject_CallObject(callable,argtup); |
Lines 460 to 473 in29acc08
| PyObject_CallObject(PyObject*callable,PyObject*args) | |
| { | |
| PyThreadState*tstate=_PyThreadState_GET(); | |
| assert(!_PyErr_Occurred(tstate)); | |
| if (args==NULL) { | |
| return_PyObject_CallNoArgsTstate(tstate,callable); | |
| } | |
| if (!PyTuple_Check(args)) { | |
| _PyErr_SetString(tstate,PyExc_TypeError, | |
| "argument list must be a tuple"); | |
| returnNULL; | |
| } | |
| return_PyObject_Call(tstate,callable,args,NULL); | |
| } |
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 Pythonpickle deserialization to unfold just fine.
payload: b'cbuiltins\nprint\n}R.'pickle:None_pickle.c: FAILURE argument list must be a tuplepickletools: 0: c GLOBAL 'builtins print' 16: } EMPTY_DICT 17: R REDUCE 18: . STOPhighest protocol among opcodes = 1I think the easiest way to remedy the discrepancy is to explicitly type check theargs parameter inpickle.py'sload_reduce() function.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Metadata
Metadata
Assignees
Projects
Status