summaryrefslogtreecommitdiffstats
path: root/Include/internal
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-04-11 09:33:27 (GMT)
committerGitHub <noreply@github.com>2019-04-11 09:33:27 (GMT)
commit2b00db68554422ec37faba2a80179a0172df6349 (patch)
tree164b39074b3563200714215ea8273c59f173feb5 /Include/internal
parent57b1a2862a99677f09614e9e456d36aae9ddd87c (diff)
downloadcpython-2b00db68554422ec37faba2a80179a0172df6349.zip
cpython-2b00db68554422ec37faba2a80179a0172df6349.tar.gz
cpython-2b00db68554422ec37faba2a80179a0172df6349.tar.bz2
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().
Diffstat (limited to 'Include/internal')
-rw-r--r--Include/internal/pycore_pymem.h25
1 files changed, 25 insertions, 0 deletions
diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h
index 1e7da87..78d457d 100644
--- a/Include/internal/pycore_pymem.h
+++ b/Include/internal/pycore_pymem.h
@@ -155,6 +155,31 @@ PyAPI_FUNC(int) _PyMem_SetDefaultAllocator(
PyMemAllocatorDomain domain,
PyMemAllocatorEx *old_alloc);
+/* Heuristic checking if a pointer value is newly allocated
+ (uninitialized) or newly freed. The pointer is not dereferenced, only the
+ pointer value is checked.
+
+ The heuristic relies on the debug hooks on Python memory allocators which
+ fills newly allocated memory with CLEANBYTE (0xCB) and newly freed memory
+ with DEADBYTE (0xDB). Detect also "untouchable bytes" marked
+ with FORBIDDENBYTE (0xFB). */
+static inline int _PyMem_IsPtrFreed(void *ptr)
+{
+ uintptr_t value = (uintptr_t)ptr;
+#if SIZEOF_VOID_P == 8
+ return (value == (uintptr_t)0xCBCBCBCBCBCBCBCB
+ || value == (uintptr_t)0xDBDBDBDBDBDBDBDB
+ || value == (uintptr_t)0xFBFBFBFBFBFBFBFB
+ );
+#elif SIZEOF_VOID_P == 4
+ return (value == (uintptr_t)0xCBCBCBCB
+ || value == (uintptr_t)0xDBDBDBDB
+ || value == (uintptr_t)0xFBFBFBFB);
+#else
+# error "unknown pointer size"
+#endif
+}
+
#ifdef __cplusplus
}
#endif