]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-124513: Check args in framelocalsproxy_new() (GH-124515) (#124539)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 30 Sep 2024 01:03:00 +0000 (03:03 +0200)
committerGitHub <noreply@github.com>
Mon, 30 Sep 2024 01:03:00 +0000 (18:03 -0700)
gh-124513: Check args in framelocalsproxy_new() (GH-124515)

Fix a crash in FrameLocalsProxy constructor: check the number of
arguments.
(cherry picked from commit d6954b6421aa34afd280df9c44ded21a2348a6ea)

Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/test_frame.py
Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-14-45-56.gh-issue-124513.ywiXtr.rst [new file with mode: 0644]
Objects/frameobject.c

index 4c79813f12ada28de6c6ec03144ed066799f5028..eedd66a4f125bc60e32b6f5b94b1dcbf1e868b85 100644 (file)
@@ -496,6 +496,27 @@ class TestFrameLocals(unittest.TestCase):
                 with self.assertRaises(TypeError):
                     proxy[obj] = 0
 
+    def test_constructor(self):
+        FrameLocalsProxy = type([sys._getframe().f_locals
+                                 for x in range(1)][0])
+        self.assertEqual(FrameLocalsProxy.__name__, 'FrameLocalsProxy')
+
+        def make_frame():
+            x = 1
+            y = 2
+            return sys._getframe()
+
+        proxy = FrameLocalsProxy(make_frame())
+        self.assertEqual(proxy, {'x': 1, 'y': 2})
+
+        # constructor expects 1 frame argument
+        with self.assertRaises(TypeError):
+            FrameLocalsProxy()     # no arguments
+        with self.assertRaises(TypeError):
+            FrameLocalsProxy(123)  # wrong type
+        with self.assertRaises(TypeError):
+            FrameLocalsProxy(frame=sys._getframe())  # no keyword arguments
+
 
 class FrameLocalsProxyMappingTests(mapping_tests.TestHashMappingProtocol):
     """Test that FrameLocalsProxy behaves like a Mapping (with exceptions)"""
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-14-45-56.gh-issue-124513.ywiXtr.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-14-45-56.gh-issue-124513.ywiXtr.rst
new file mode 100644 (file)
index 0000000..691e03b
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a crash in FrameLocalsProxy constructor: check the number of arguments.
+Patch by Victor Stinner.
index 90b975b3f43fdb1ed32bb6c13283d8e6d9e420db..23a82ae6736020b1361c8f5598aa796ebf26fa24 100644 (file)
@@ -308,14 +308,31 @@ framelocalsproxy_dealloc(PyObject *self)
 static PyObject *
 framelocalsproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
+    if (PyTuple_GET_SIZE(args) != 1) {
+        PyErr_Format(PyExc_TypeError,
+                     "FrameLocalsProxy expected 1 argument, got %zd",
+                     PyTuple_GET_SIZE(args));
+        return NULL;
+    }
+    PyObject *item = PyTuple_GET_ITEM(args, 0);
+
+    if (!PyFrame_Check(item)) {
+        PyErr_Format(PyExc_TypeError, "expect frame, not %T", item);
+        return NULL;
+    }
+    PyFrameObject *frame = (PyFrameObject*)item;
+
+    if (kwds != NULL && PyDict_Size(kwds) != 0) {
+        PyErr_SetString(PyExc_TypeError,
+                        "FrameLocalsProxy takes no keyword arguments");
+        return 0;
+    }
+
     PyFrameLocalsProxyObject *self = (PyFrameLocalsProxyObject *)type->tp_alloc(type, 0);
     if (self == NULL) {
         return NULL;
     }
 
-    PyFrameObject *frame = (PyFrameObject*)PyTuple_GET_ITEM(args, 0);
-    assert(PyFrame_Check(frame));
-
     ((PyFrameLocalsProxyObject*)self)->frame = (PyFrameObject*)Py_NewRef(frame);
 
     return (PyObject *)self;