summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNGRsoftlab <78017794+NGRsoftlab@users.noreply.github.com>2024-05-02 13:43:03 (GMT)
committerGitHub <noreply@github.com>2024-05-02 13:43:03 (GMT)
commit7d2ffada0a6490e6839697f729bcd80380e9f561 (patch)
tree2406de9015978d0b64b082e17d711677c1743b0d
parent7c97dc8c9594c71bd3d1f69758a27de45f57e4c3 (diff)
downloadcpython-7d2ffada0a6490e6839697f729bcd80380e9f561.zip
cpython-7d2ffada0a6490e6839697f729bcd80380e9f561.tar.gz
cpython-7d2ffada0a6490e6839697f729bcd80380e9f561.tar.bz2
gh-116180: Check the globals argument in PyRun_* C API (GH-116637)
It used to crash when passing NULL or non-dict as globals. Now it sets a SystemError.
-rw-r--r--Lib/test/test_capi/test_run.py36
-rw-r--r--Python/pythonrun.c21
2 files changed, 36 insertions, 21 deletions
diff --git a/Lib/test/test_capi/test_run.py b/Lib/test/test_capi/test_run.py
index 3a39027..894f66b 100644
--- a/Lib/test/test_capi/test_run.py
+++ b/Lib/test/test_capi/test_run.py
@@ -11,6 +11,10 @@ Py_file_input = _testcapi.Py_file_input
Py_eval_input = _testcapi.Py_eval_input
+class DictSubclass(dict):
+ pass
+
+
class CAPITest(unittest.TestCase):
# TODO: Test the following functions:
#
@@ -50,15 +54,19 @@ class CAPITest(unittest.TestCase):
self.assertRaises(TypeError, run, b'a\n', dict(a=1), [])
self.assertRaises(TypeError, run, b'a\n', dict(a=1), 1)
+ self.assertIsNone(run(b'a\n', DictSubclass(a=1)))
+ self.assertIsNone(run(b'a\n', DictSubclass(), dict(a=1)))
+ self.assertRaises(NameError, run, b'a\n', DictSubclass())
+
self.assertIsNone(run(b'\xc3\xa4\n', {'\xe4': 1}))
self.assertRaises(SyntaxError, run, b'\xe4\n', {})
- # CRASHES run(b'a\n', NULL)
- # CRASHES run(b'a\n', NULL, {})
- # CRASHES run(b'a\n', NULL, dict(a=1))
- # CRASHES run(b'a\n', UserDict())
- # CRASHES run(b'a\n', UserDict(), {})
- # CRASHES run(b'a\n', UserDict(), dict(a=1))
+ self.assertRaises(SystemError, run, b'a\n', NULL)
+ self.assertRaises(SystemError, run, b'a\n', NULL, {})
+ self.assertRaises(SystemError, run, b'a\n', NULL, dict(a=1))
+ self.assertRaises(SystemError, run, b'a\n', UserDict())
+ self.assertRaises(SystemError, run, b'a\n', UserDict(), {})
+ self.assertRaises(SystemError, run, b'a\n', UserDict(), dict(a=1))
# CRASHES run(NULL, {})
@@ -82,12 +90,16 @@ class CAPITest(unittest.TestCase):
self.assertRaises(TypeError, run, dict(a=1), [])
self.assertRaises(TypeError, run, dict(a=1), 1)
- # CRASHES run(NULL)
- # CRASHES run(NULL, {})
- # CRASHES run(NULL, dict(a=1))
- # CRASHES run(UserDict())
- # CRASHES run(UserDict(), {})
- # CRASHES run(UserDict(), dict(a=1))
+ self.assertIsNone(run(DictSubclass(a=1)))
+ self.assertIsNone(run(DictSubclass(), dict(a=1)))
+ self.assertRaises(NameError, run, DictSubclass())
+
+ self.assertRaises(SystemError, run, NULL)
+ self.assertRaises(SystemError, run, NULL, {})
+ self.assertRaises(SystemError, run, NULL, dict(a=1))
+ self.assertRaises(SystemError, run, UserDict())
+ self.assertRaises(SystemError, run, UserDict(), {})
+ self.assertRaises(SystemError, run, UserDict(), dict(a=1))
@unittest.skipUnless(TESTFN_UNDECODABLE, 'only works if there are undecodable paths')
@unittest.skipIf(os.name == 'nt', 'does not work on Windows')
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 2970248..31213ae 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1275,17 +1275,20 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
_PyRuntime.signals.unhandled_keyboard_interrupt = 0;
/* Set globals['__builtins__'] if it doesn't exist */
- if (globals != NULL) {
- int has_builtins = PyDict_ContainsString(globals, "__builtins__");
- if (has_builtins < 0) {
+ if (!globals || !PyDict_Check(globals)) {
+ PyErr_SetString(PyExc_SystemError, "globals must be a real dict");
+ return NULL;
+ }
+ int has_builtins = PyDict_ContainsString(globals, "__builtins__");
+ if (has_builtins < 0) {
+ return NULL;
+ }
+ if (!has_builtins) {
+ if (PyDict_SetItemString(globals, "__builtins__",
+ tstate->interp->builtins) < 0)
+ {
return NULL;
}
- if (!has_builtins) {
- if (PyDict_SetItemString(globals, "__builtins__",
- tstate->interp->builtins) < 0) {
- return NULL;
- }
- }
}
v = PyEval_EvalCode((PyObject*)co, globals, locals);