Skip to content

Commit

Permalink
Issue #13204: Calling sys.flags.__new__ would crash the interpreter, …
Browse files Browse the repository at this point in the history
…now it raises a TypeError.
  • Loading branch information
pitrou committed Apr 28, 2014
1 parent 94ba146 commit 871dfc4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
20 changes: 20 additions & 0 deletions Lib/test/test_sys.py
Expand Up @@ -519,6 +519,26 @@ def test_sys_flags(self):
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()

Expand Down
3 changes: 3 additions & 0 deletions Misc/NEWS
Expand Up @@ -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.

Expand Down
13 changes: 10 additions & 3 deletions Python/sysmodule.c
Expand Up @@ -1622,14 +1622,14 @@ PyObject *
_PySys_Init(void)
{
PyObject *m, *sysdict, *version_info;
int res;

m = PyModule_Create(&sysmodule);
if (m == NULL)
return NULL;
sysdict = PyModule_GetDict(m);
#define SET_SYS_FROM_STRING_BORROW(key, value) \
do { \
int res; \
PyObject *v = (value); \
if (v == NULL) \
return NULL; \
Expand All @@ -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; \
Expand Down Expand Up @@ -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));
Expand All @@ -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 */
Expand All @@ -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) */
Expand Down

0 comments on commit 871dfc4

Please sign in to comment.