Skip to content

Commit d6954b6

Browse files
authored
gh-124513: Check args in framelocalsproxy_new() (#124515)
Fix a crash in FrameLocalsProxy constructor: check the number of arguments.
1 parent 0d9d56c commit d6954b6

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
@@ -494,6 +494,27 @@ class ObjectSubclass:
494494
with self.assertRaises(TypeError):
495495
proxy[obj] = 0
496496

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

498519
class FrameLocalsProxyMappingTests(mapping_tests.TestHashMappingProtocol):
499520
"""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
@@ -310,14 +310,31 @@ framelocalsproxy_dealloc(PyObject *self)
310310
static PyObject *
311311
framelocalsproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
312312
{
313+
if (PyTuple_GET_SIZE(args) != 1) {
314+
PyErr_Format(PyExc_TypeError,
315+
"FrameLocalsProxy expected 1 argument, got %zd",
316+
PyTuple_GET_SIZE(args));
317+
return NULL;
318+
}
319+
PyObject *item = PyTuple_GET_ITEM(args, 0);
320+
321+
if (!PyFrame_Check(item)) {
322+
PyErr_Format(PyExc_TypeError, "expect frame, not %T", item);
323+
return NULL;
324+
}
325+
PyFrameObject *frame = (PyFrameObject*)item;
326+
327+
if (kwds != NULL && PyDict_Size(kwds) != 0) {
328+
PyErr_SetString(PyExc_TypeError,
329+
"FrameLocalsProxy takes no keyword arguments");
330+
return 0;
331+
}
332+
313333
PyFrameLocalsProxyObject *self = (PyFrameLocalsProxyObject *)type->tp_alloc(type, 0);
314334
if (self == NULL) {
315335
return NULL;
316336
}
317337

318-
PyFrameObject *frame = (PyFrameObject*)PyTuple_GET_ITEM(args, 0);
319-
assert(PyFrame_Check(frame));
320-
321338
((PyFrameLocalsProxyObject*)self)->frame = (PyFrameObject*)Py_NewRef(frame);
322339

323340
return (PyObject *)self;

0 commit comments

Comments
 (0)