Skip to content

Commit 62f691f

Browse files
[3.13] gh-124513: Check args in framelocalsproxy_new() (GH-124515) (#124539)
gh-124513: Check args in framelocalsproxy_new() (GH-124515) Fix a crash in FrameLocalsProxy constructor: check the number of arguments. (cherry picked from commit d6954b6) Co-authored-by: Victor Stinner <[email protected]>
1 parent c7f9332 commit 62f691f

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

Lib/test/test_frame.py

+21
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,27 @@ class ObjectSubclass:
496496
with self.assertRaises(TypeError):
497497
proxy[obj] = 0
498498

499+
def test_constructor(self):
500+
FrameLocalsProxy = type([sys._getframe().f_locals
501+
for x in range(1)][0])
502+
self.assertEqual(FrameLocalsProxy.__name__, 'FrameLocalsProxy')
503+
504+
def make_frame():
505+
x = 1
506+
y = 2
507+
return sys._getframe()
508+
509+
proxy = FrameLocalsProxy(make_frame())
510+
self.assertEqual(proxy, {'x': 1, 'y': 2})
511+
512+
# constructor expects 1 frame argument
513+
with self.assertRaises(TypeError):
514+
FrameLocalsProxy() # no arguments
515+
with self.assertRaises(TypeError):
516+
FrameLocalsProxy(123) # wrong type
517+
with self.assertRaises(TypeError):
518+
FrameLocalsProxy(frame=sys._getframe()) # no keyword arguments
519+
499520

500521
class FrameLocalsProxyMappingTests(mapping_tests.TestHashMappingProtocol):
501522
"""Test that FrameLocalsProxy behaves like a Mapping (with exceptions)"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in FrameLocalsProxy constructor: check the number of arguments.
2+
Patch by Victor Stinner.

Objects/frameobject.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,31 @@ framelocalsproxy_dealloc(PyObject *self)
308308
static PyObject *
309309
framelocalsproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
310310
{
311+
if (PyTuple_GET_SIZE(args) != 1) {
312+
PyErr_Format(PyExc_TypeError,
313+
"FrameLocalsProxy expected 1 argument, got %zd",
314+
PyTuple_GET_SIZE(args));
315+
return NULL;
316+
}
317+
PyObject *item = PyTuple_GET_ITEM(args, 0);
318+
319+
if (!PyFrame_Check(item)) {
320+
PyErr_Format(PyExc_TypeError, "expect frame, not %T", item);
321+
return NULL;
322+
}
323+
PyFrameObject *frame = (PyFrameObject*)item;
324+
325+
if (kwds != NULL && PyDict_Size(kwds) != 0) {
326+
PyErr_SetString(PyExc_TypeError,
327+
"FrameLocalsProxy takes no keyword arguments");
328+
return 0;
329+
}
330+
311331
PyFrameLocalsProxyObject *self = (PyFrameLocalsProxyObject *)type->tp_alloc(type, 0);
312332
if (self == NULL) {
313333
return NULL;
314334
}
315335

316-
PyFrameObject *frame = (PyFrameObject*)PyTuple_GET_ITEM(args, 0);
317-
assert(PyFrame_Check(frame));
318-
319336
((PyFrameLocalsProxyObject*)self)->frame = (PyFrameObject*)Py_NewRef(frame);
320337

321338
return (PyObject *)self;

0 commit comments

Comments
 (0)