]> granicus.if.org Git - python/commitdiff
Issue #13204: Calling sys.flags.__new__ would crash the interpreter, now it raises...
authorAntoine Pitrou <solipsis@pitrou.net>
Mon, 28 Apr 2014 11:07:06 +0000 (13:07 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Mon, 28 Apr 2014 11:07:06 +0000 (13:07 +0200)
Lib/test/test_sys.py
Misc/NEWS
Python/sysmodule.c

index 5a9699ff2045f8725575966ae019bdffd30d634f..a68ed08df724c498ccdabf319277e0f179aa5b27 100644 (file)
@@ -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()
 
index e3c8810cd770d1765076ca139aae50158eba48bb..856520fb2bc3ea0d69c71480b4978f3301cda2e5 100644 (file)
--- 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.
 
index 64de2bf258e8489a771e5d5f82b8833cd43501c7..2366a8c66fb9cc1939c64d94b510a8ef8986ee4b 100644 (file)
@@ -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) */