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 <vstinner@python.org>
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

Lines changed: 21 additions & 0 deletions
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)"""
Lines changed: 2 additions & 0 deletions
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

Lines changed: 20 additions & 3 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy