@@ -209,6 +209,64 @@ slp_reduce_frame(PyFrameObject * frame) {
209
209
return PyObject_CallFunctionObjArgs (reduce_frame_func , (PyObject * )frame , NULL );
210
210
}
211
211
212
+ /* Helper function for gen_setstate and tb_setstate.
213
+ * It unwraps the first argument of the args tuple, if it is a _Frame_Wrapper.
214
+ * Returns a new reference to an argument tuple.
215
+ *
216
+ * This functionality is required, to adhere to the __reduce__/__setstate__ protocol.
217
+ * It requires, that __setstate__ accepts the state returned by __reduce__. (copy.copy()
218
+ * depends on it.)
219
+ */
220
+ static PyObject *
221
+ unwrap_frame_arg (PyObject * args ) {
222
+ PyObject * wrapper_type , * arg0 , * result ;
223
+ int is_instance ;
224
+ Py_ssize_t len , i ;
225
+
226
+ if (!PyTuple_Check (args ) || (len = PyTuple_Size (args )) < 1 ) {
227
+ if (len < 0 )
228
+ return NULL ;
229
+ Py_INCREF (args );
230
+ return args ;
231
+ }
232
+ if ((arg0 = PyTuple_GetItem (args , 0 )) == NULL ) /* arg0 is a borrowed reference */
233
+ return NULL ;
234
+ if ((wrapper_type = PyObject_GetAttrString (reduce_frame_func , "__self__" )) == NULL )
235
+ return NULL ;
236
+ is_instance = PyObject_IsInstance (arg0 , wrapper_type );
237
+ Py_DECREF (wrapper_type );
238
+ if (is_instance == 0 ) {
239
+ Py_INCREF (args );
240
+ return args ;
241
+ } else if (is_instance == -1 ) {
242
+ return NULL ;
243
+ }
244
+ if ((arg0 = PyObject_GetAttrString (arg0 , "frame" )) == NULL )
245
+ return NULL ;
246
+ if ((result = PyTuple_New (len )) == NULL ) {
247
+ Py_DECREF (arg0 );
248
+ return NULL ;
249
+ }
250
+ if (PyTuple_SetItem (result , 0 , arg0 )) { /* steals ref to arg0 */
251
+ Py_DECREF (arg0 );
252
+ Py_DECREF (result );
253
+ return NULL ;
254
+ }
255
+ for (i = 1 ; i < len ; i ++ ) {
256
+ if ((arg0 = PyTuple_GetItem (args , i )) == NULL ) {
257
+ Py_DECREF (result );
258
+ return NULL ;
259
+ }
260
+ /* arg0 is a borrowed reference */
261
+ Py_INCREF (arg0 );
262
+ if (PyTuple_SetItem (result , i , arg0 )) { /* steals ref to arg0 */
263
+ Py_DECREF (arg0 );
264
+ Py_DECREF (result );
265
+ return NULL ;
266
+ }
267
+ }
268
+ return result ;
269
+ }
212
270
213
271
static struct PyMethodDef _new_methoddef [] = {
214
272
{"__new__" , (PyCFunction )_new_wrapper , METH_VARARGS | METH_KEYWORDS ,
@@ -1230,11 +1288,17 @@ tb_setstate(PyObject *self, PyObject *args)
1230
1288
1231
1289
if (is_wrong_type (Py_TYPE (tb ))) return NULL ;
1232
1290
1291
+ if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
1292
+ return NULL ;
1293
+
1233
1294
if (!PyArg_ParseTuple (args ,
1234
1295
"O!ii|O!:traceback" ,
1235
1296
& PyFrame_Type , & frame ,
1236
- & lasti , & lineno ,& PyTraceBack_Type , & next ))
1297
+ & lasti , & lineno ,& PyTraceBack_Type , & next )) {
1298
+ Py_DECREF (args );
1237
1299
return NULL ;
1300
+ }
1301
+ Py_DECREF (args );
1238
1302
1239
1303
Py_XINCREF (next );
1240
1304
tb -> tb_next = next ;
@@ -2319,9 +2383,16 @@ gen_setstate(PyObject *self, PyObject *args)
2319
2383
PyObject * qualname = NULL ;
2320
2384
2321
2385
if (is_wrong_type (Py_TYPE (self ))) return NULL ;
2386
+
2387
+ if ((args = unwrap_frame_arg (args )) == NULL ) /* now args is a counted ref! */
2388
+ return NULL ;
2389
+
2322
2390
if (!PyArg_ParseTuple (args , "O!i|OO:generator" ,
2323
- & PyFrame_Type , & f , & gi_running , & name , & qualname ))
2391
+ & PyFrame_Type , & f , & gi_running , & name , & qualname )) {
2392
+ Py_DECREF (args );
2324
2393
return NULL ;
2394
+ }
2395
+ Py_DECREF (args );
2325
2396
2326
2397
if (name == NULL ) {
2327
2398
name = f -> f_code -> co_name ;
0 commit comments