bpo-36389: _PyObject_IsFreed() now also detects uninitialized memory (GH-12770)

Replace _PyMem_IsFreed() function with _PyMem_IsPtrFreed() inline
function. The function is now way more efficient, it became a simple
comparison on integers, rather than a short loop. It detects also
uninitialized bytes and "forbidden bytes" filled by debug hooks
on memory allocators.

Add unit tests on _PyObject_IsFreed().
This commit is contained in:
Victor Stinner 2019-04-11 11:33:27 +02:00 committed by GitHub
parent 57b1a2862a
commit 2b00db6855
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 27 deletions

View file

@ -526,6 +526,29 @@ class PyMemDebugTests(unittest.TestCase):
code = 'import _testcapi; _testcapi.pyobject_malloc_without_gil()'
self.check_malloc_without_gil(code)
def check_pyobject_is_freed(self, func):
code = textwrap.dedent('''
import gc, os, sys, _testcapi
# Disable the GC to avoid crash on GC collection
gc.disable()
obj = _testcapi.{func}()
error = (_testcapi.pyobject_is_freed(obj) == False)
# Exit immediately to avoid a crash while deallocating
# the invalid object
os._exit(int(error))
''')
code = code.format(func=func)
assert_python_ok('-c', code, PYTHONMALLOC=self.PYTHONMALLOC)
def test_pyobject_is_freed_uninitialized(self):
self.check_pyobject_is_freed('pyobject_uninitialized')
def test_pyobject_is_freed_forbidden_bytes(self):
self.check_pyobject_is_freed('pyobject_forbidden_bytes')
def test_pyobject_is_freed_free(self):
self.check_pyobject_is_freed('pyobject_freed')
class PyMemMallocDebugTests(PyMemDebugTests):
PYTHONMALLOC = 'malloc_debug'