From 871dfc41d37b02a7af6eb03028edc6702f24fd1d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 28 Apr 2014 13:07:06 +0200 Subject: Issue #13204: Calling sys.flags.__new__ would crash the interpreter, now it raises a TypeError. --- Lib/test/test_sys.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ Python/sysmodule.c | 13 ++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 5a9699f..a68ed08 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -519,6 +519,26 @@ class SysModuleTest(unittest.TestCase): self.assertTrue(repr(sys.flags)) self.assertEqual(len(sys.flags), len(attrs)) + def assert_raise_on_new_sys_type(self, sys_attr): + # Users are intentionally prevented from creating new instances of + # sys.flags, sys.version_info, and sys.getwindowsversion. + attr_type = type(sys_attr) + with self.assertRaises(TypeError): + attr_type() + with self.assertRaises(TypeError): + attr_type.__new__(attr_type) + + def test_sys_flags_no_instantiation(self): + self.assert_raise_on_new_sys_type(sys.flags) + + def test_sys_version_info_no_instantiation(self): + self.assert_raise_on_new_sys_type(sys.version_info) + + def test_sys_getwindowsversion_no_instantiation(self): + # Skip if not being run on Windows. + test.support.get_attribute(sys, "getwindowsversion") + self.assert_raise_on_new_sys_type(sys.getwindowsversion()) + def test_clear_type_cache(self): sys._clear_type_cache() diff --git a/Misc/NEWS b/Misc/NEWS index e3c8810..856520f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Core and Builtins Library ------- +- Issue #13204: Calling sys.flags.__new__ would crash the interpreter, + now it raises a TypeError. + - Issue #19385: Make operations on a closed dbm.dumb database always raise the same exception. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 64de2bf..2366a8c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1622,6 +1622,7 @@ PyObject * _PySys_Init(void) { PyObject *m, *sysdict, *version_info; + int res; m = PyModule_Create(&sysmodule); if (m == NULL) @@ -1629,7 +1630,6 @@ _PySys_Init(void) sysdict = PyModule_GetDict(m); #define SET_SYS_FROM_STRING_BORROW(key, value) \ do { \ - int res; \ PyObject *v = (value); \ if (v == NULL) \ return NULL; \ @@ -1640,7 +1640,6 @@ _PySys_Init(void) } while (0) #define SET_SYS_FROM_STRING(key, value) \ do { \ - int res; \ PyObject *v = (value); \ if (v == NULL) \ return NULL; \ @@ -1759,6 +1758,9 @@ _PySys_Init(void) /* prevent user from creating new instances */ VersionInfoType.tp_init = NULL; VersionInfoType.tp_new = NULL; + res = PyDict_DelItemString(VersionInfoType.tp_dict, "__new__"); + if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_Clear(); /* implementation */ SET_SYS_FROM_STRING("implementation", make_impl_info(version_info)); @@ -1772,7 +1774,9 @@ _PySys_Init(void) /* prevent user from creating new instances */ FlagsType.tp_init = NULL; FlagsType.tp_new = NULL; - + res = PyDict_DelItemString(FlagsType.tp_dict, "__new__"); + if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_Clear(); #if defined(MS_WINDOWS) /* getwindowsversion */ @@ -1783,6 +1787,9 @@ _PySys_Init(void) /* prevent user from creating new instances */ WindowsVersionType.tp_init = NULL; WindowsVersionType.tp_new = NULL; + res = PyDict_DelItemString(WindowsVersionType.tp_dict, "__new__"); + if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_Clear(); #endif /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ -- cgit v0.12