bpo-43916: Apply Py_TPFLAGS_DISALLOW_INSTANTIATION to selected types (GH-25748)

Apply Py_TPFLAGS_DISALLOW_INSTANTIATION to the following types:

* _dbm.dbm
* _gdbm.gdbm
* _multibytecodec.MultibyteCodec
* _sre..SRE_Scanner
* _thread._localdummy
* _thread.lock
* _winapi.Overlapped
* array.arrayiterator
* functools.KeyWrapper
* functools._lru_list_elem
* pyexpat.xmlparser
* re.Match
* re.Pattern
* unicodedata.UCD
* zlib.Compress
* zlib.Decompress
This commit is contained in:
Erlend Egeberg Aasland 2021-04-30 16:04:57 +02:00 committed by GitHub
parent 387397f8a4
commit 9746cda705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 87 additions and 28 deletions

View File

@ -40,6 +40,12 @@ class MiscTest(unittest.TestCase):
self.assertRaises(TypeError, array.array, 'xx') self.assertRaises(TypeError, array.array, 'xx')
self.assertRaises(ValueError, array.array, 'x') self.assertRaises(ValueError, array.array, 'x')
@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
tp = type(iter(array.array('I')))
self.assertRaises(TypeError, tp)
@support.cpython_only @support.cpython_only
def test_immutable(self): def test_immutable(self):
# bpo-43908: check that array.array is immutable # bpo-43908: check that array.array is immutable

View File

@ -6,7 +6,7 @@ import sys
import tempfile import tempfile
import unittest import unittest
from test.support import requires, verbose, SaveSignals from test.support import requires, verbose, SaveSignals, cpython_only
from test.support.import_helper import import_module from test.support.import_helper import import_module
# Optionally test curses module. This currently requires that the # Optionally test curses module. This currently requires that the
@ -1046,8 +1046,10 @@ class TestCurses(unittest.TestCase):
panel.set_userptr(A()) panel.set_userptr(A())
panel.set_userptr(None) panel.set_userptr(None)
@cpython_only
@requires_curses_func('panel') @requires_curses_func('panel')
def test_new_curses_panel(self): def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
w = curses.newwin(10, 10) w = curses.newwin(10, 10)
panel = curses.panel.new_panel(w) panel = curses.panel.new_panel(w)
self.assertRaises(TypeError, type(panel)) self.assertRaises(TypeError, type(panel))

View File

@ -1,5 +1,5 @@
from test import support from test import support
from test.support import import_helper from test.support import import_helper, cpython_only
gdbm = import_helper.import_module("dbm.gnu") #skip if not supported gdbm = import_helper.import_module("dbm.gnu") #skip if not supported
import unittest import unittest
import os import os
@ -27,6 +27,13 @@ class TestGdbm(unittest.TestCase):
self.g.close() self.g.close()
unlink(filename) unlink(filename)
@cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
self.g = gdbm.open(filename, 'c')
tp = type(self.g)
self.assertRaises(TypeError, tp)
def test_key_methods(self): def test_key_methods(self):
self.g = gdbm.open(filename, 'c') self.g = gdbm.open(filename, 'c')
self.assertEqual(self.g.keys(), []) self.assertEqual(self.g.keys(), [])

View File

@ -948,6 +948,12 @@ class TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
if c_functools: if c_functools:
cmp_to_key = c_functools.cmp_to_key cmp_to_key = c_functools.cmp_to_key
@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
tp = type(c_functools.cmp_to_key(None))
self.assertRaises(TypeError, tp)
class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase): class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):
cmp_to_key = staticmethod(py_functools.cmp_to_key) cmp_to_key = staticmethod(py_functools.cmp_to_key)

View File

@ -2215,6 +2215,15 @@ class ImplementationTest(unittest.TestCase):
self.assertGreaterEqual(sre_compile.MAXREPEAT, 0) self.assertGreaterEqual(sre_compile.MAXREPEAT, 0)
self.assertGreaterEqual(sre_compile.MAXGROUPS, 0) self.assertGreaterEqual(sre_compile.MAXGROUPS, 0)
@cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
self.assertRaises(TypeError, re.Match)
self.assertRaises(TypeError, re.Pattern)
pat = re.compile("")
tp = type(pat.scanner(""))
self.assertRaises(TypeError, tp)
class ExternalTests(unittest.TestCase): class ExternalTests(unittest.TestCase):

View File

@ -736,8 +736,11 @@ class TclTest(unittest.TestCase):
check('{\n') check('{\n')
check('}\n') check('}\n')
@support.cpython_only
def test_new_tcl_obj(self): def test_new_tcl_obj(self):
self.assertRaises(TypeError, _tkinter.Tcl_Obj) self.assertRaises(TypeError, _tkinter.Tcl_Obj)
self.assertRaises(TypeError, _tkinter.TkttType)
self.assertRaises(TypeError, _tkinter.TkappType)
class BigmemTclTest(unittest.TestCase): class BigmemTclTest(unittest.TestCase):

View File

@ -119,6 +119,13 @@ class ThreadTests(BaseTestCase):
thread = threading.Thread(target=func) thread = threading.Thread(target=func)
self.assertEqual(thread.name, "Thread-5 (func)") self.assertEqual(thread.name, "Thread-5 (func)")
@cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
lock = threading.Lock()
tp = type(lock)
self.assertRaises(TypeError, tp)
# Create a bunch of threads, let each do some work, wait until all are # Create a bunch of threads, let each do some work, wait until all are
# done. # done.
def test_various_ops(self): def test_various_ops(self):

View File

@ -11,7 +11,8 @@ from http.client import HTTPException
import sys import sys
import unicodedata import unicodedata
import unittest import unittest
from test.support import open_urlresource, requires_resource, script_helper from test.support import (open_urlresource, requires_resource, script_helper,
cpython_only)
class UnicodeMethodsTest(unittest.TestCase): class UnicodeMethodsTest(unittest.TestCase):
@ -225,6 +226,11 @@ class UnicodeFunctionsTest(UnicodeDatabaseTest):
class UnicodeMiscTest(UnicodeDatabaseTest): class UnicodeMiscTest(UnicodeDatabaseTest):
@cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
self.assertRaises(TypeError, unicodedata.UCD)
def test_failed_import_during_compiling(self): def test_failed_import_during_compiling(self):
# Issue 4367 # Issue 4367
# Decoding \N escapes requires the unicodedata module. If it can't be # Decoding \N escapes requires the unicodedata module. If it can't be

View File

@ -129,6 +129,14 @@ class ExceptionTestCase(unittest.TestCase):
with self.assertRaisesRegex(OverflowError, 'int too large'): with self.assertRaisesRegex(OverflowError, 'int too large'):
zlib.decompressobj().flush(sys.maxsize + 1) zlib.decompressobj().flush(sys.maxsize + 1)
@support.cpython_only
def test_disallow_instantiation(self):
# Ensure that the type disallows instantiation (bpo-43916)
comp_type = type(zlib.compressobj())
decomp_type = type(zlib.decompressobj())
self.assertRaises(TypeError, comp_type)
self.assertRaises(TypeError, decomp_type)
class BaseCompressTestCase(object): class BaseCompressTestCase(object):
def check_big_compress_buffer(self, size, compress_func): def check_big_compress_buffer(self, size, compress_func):

View File

@ -414,7 +414,7 @@ static PyType_Spec dbmtype_spec = {
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
// which prevents to create a subclass. // which prevents to create a subclass.
// So calling PyType_GetModuleState() in this file is always safe. // So calling PyType_GetModuleState() in this file is always safe.
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = dbmtype_spec_slots, .slots = dbmtype_spec_slots,
}; };

View File

@ -546,7 +546,7 @@ static PyType_Slot keyobject_type_slots[] = {
static PyType_Spec keyobject_type_spec = { static PyType_Spec keyobject_type_spec = {
.name = "functools.KeyWrapper", .name = "functools.KeyWrapper",
.basicsize = sizeof(keyobject), .basicsize = sizeof(keyobject),
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = keyobject_type_slots .slots = keyobject_type_slots
}; };
@ -766,7 +766,7 @@ static PyType_Slot lru_list_elem_type_slots[] = {
static PyType_Spec lru_list_elem_type_spec = { static PyType_Spec lru_list_elem_type_spec = {
.name = "functools._lru_list_elem", .name = "functools._lru_list_elem",
.basicsize = sizeof(lru_list_elem), .basicsize = sizeof(lru_list_elem),
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = lru_list_elem_type_slots .slots = lru_list_elem_type_slots
}; };

View File

@ -570,7 +570,7 @@ static PyType_Spec gdbmtype_spec = {
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
// which prevents to create a subclass. // which prevents to create a subclass.
// So calling PyType_GetModuleState() in this file is always safe. // So calling PyType_GetModuleState() in this file is always safe.
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = gdbmtype_spec_slots, .slots = gdbmtype_spec_slots,
}; };

View File

@ -2690,7 +2690,8 @@ static PyType_Spec pattern_spec = {
.name = "re.Pattern", .name = "re.Pattern",
.basicsize = sizeof(PatternObject), .basicsize = sizeof(PatternObject),
.itemsize = sizeof(SRE_CODE), .itemsize = sizeof(SRE_CODE),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = pattern_slots, .slots = pattern_slots,
}; };
@ -2755,7 +2756,8 @@ static PyType_Spec match_spec = {
.name = "re.Match", .name = "re.Match",
.basicsize = sizeof(MatchObject), .basicsize = sizeof(MatchObject),
.itemsize = sizeof(Py_ssize_t), .itemsize = sizeof(Py_ssize_t),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = match_slots, .slots = match_slots,
}; };
@ -2781,7 +2783,8 @@ static PyType_Slot scanner_slots[] = {
static PyType_Spec scanner_spec = { static PyType_Spec scanner_spec = {
.name = "_" SRE_MODULE ".SRE_Scanner", .name = "_" SRE_MODULE ".SRE_Scanner",
.basicsize = sizeof(ScannerObject), .basicsize = sizeof(ScannerObject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = scanner_slots, .slots = scanner_slots,
}; };

View File

@ -312,7 +312,8 @@ static PyType_Slot lock_type_slots[] = {
static PyType_Spec lock_type_spec = { static PyType_Spec lock_type_spec = {
.name = "_thread.lock", .name = "_thread.lock",
.basicsize = sizeof(lockobject), .basicsize = sizeof(lockobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = lock_type_slots, .slots = lock_type_slots,
}; };
@ -683,7 +684,7 @@ static PyType_Slot local_dummy_type_slots[] = {
static PyType_Spec local_dummy_type_spec = { static PyType_Spec local_dummy_type_spec = {
.name = "_thread._localdummy", .name = "_thread._localdummy",
.basicsize = sizeof(localdummyobject), .basicsize = sizeof(localdummyobject),
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = local_dummy_type_slots, .slots = local_dummy_type_slots,
}; };

View File

@ -331,7 +331,7 @@ static PyType_Slot winapi_overlapped_type_slots[] = {
static PyType_Spec winapi_overlapped_type_spec = { static PyType_Spec winapi_overlapped_type_spec = {
.name = "_winapi.Overlapped", .name = "_winapi.Overlapped",
.basicsize = sizeof(OverlappedObject), .basicsize = sizeof(OverlappedObject),
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = winapi_overlapped_type_slots, .slots = winapi_overlapped_type_slots,
}; };

View File

@ -2987,7 +2987,8 @@ static PyType_Slot arrayiter_slots[] = {
static PyType_Spec arrayiter_spec = { static PyType_Spec arrayiter_spec = {
.name = "array.arrayiterator", .name = "array.arrayiterator",
.basicsize = sizeof(arrayiterobject), .basicsize = sizeof(arrayiterobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = arrayiter_slots, .slots = arrayiter_slots,
}; };

View File

@ -748,7 +748,8 @@ static PyType_Slot multibytecodec_slots[] = {
static PyType_Spec multibytecodec_spec = { static PyType_Spec multibytecodec_spec = {
.name = MODULE_NAME ".MultibyteCodec", .name = MODULE_NAME ".MultibyteCodec",
.basicsize = sizeof(MultibyteCodecObject), .basicsize = sizeof(MultibyteCodecObject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = multibytecodec_slots, .slots = multibytecodec_slots,
}; };

View File

@ -1506,7 +1506,8 @@ static PyType_Slot _xml_parse_type_spec_slots[] = {
static PyType_Spec _xml_parse_type_spec = { static PyType_Spec _xml_parse_type_spec = {
.name = "pyexpat.xmlparser", .name = "pyexpat.xmlparser",
.basicsize = sizeof(xmlparseobject), .basicsize = sizeof(xmlparseobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DISALLOW_INSTANTIATION),
.slots = _xml_parse_type_spec_slots, .slots = _xml_parse_type_spec_slots,
}; };

View File

@ -1454,7 +1454,7 @@ static PyType_Slot ucd_type_slots[] = {
static PyType_Spec ucd_type_spec = { static PyType_Spec ucd_type_spec = {
.name = "unicodedata.UCD", .name = "unicodedata.UCD",
.basicsize = sizeof(PreviousDBVersion), .basicsize = sizeof(PreviousDBVersion),
.flags = Py_TPFLAGS_DEFAULT, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.slots = ucd_type_slots .slots = ucd_type_slots
}; };

View File

@ -1386,11 +1386,10 @@ static PyType_Slot Comptype_slots[] = {
}; };
static PyType_Spec Comptype_spec = { static PyType_Spec Comptype_spec = {
"zlib.Compress", .name = "zlib.Compress",
sizeof(compobject), .basicsize = sizeof(compobject),
0, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Py_TPFLAGS_DEFAULT, .slots= Comptype_slots,
Comptype_slots
}; };
static PyType_Slot Decomptype_slots[] = { static PyType_Slot Decomptype_slots[] = {
@ -1401,11 +1400,10 @@ static PyType_Slot Decomptype_slots[] = {
}; };
static PyType_Spec Decomptype_spec = { static PyType_Spec Decomptype_spec = {
"zlib.Decompress", .name = "zlib.Decompress",
sizeof(compobject), .basicsize = sizeof(compobject),
0, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Py_TPFLAGS_DEFAULT, .slots = Decomptype_slots,
Decomptype_slots
}; };
PyDoc_STRVAR(zlib_module_documentation, PyDoc_STRVAR(zlib_module_documentation,