Skip to content

Commit 4c409be

Browse files
authored
bpo-36389: Change PyMem_SetupDebugHooks() constants (GH-12782)
Modify CLEANBYTE, DEADDYTE and FORBIDDENBYTE constants: use 0xCD, 0xDD and 0xFD, rather than 0xCB, 0xBB and 0xFB, to use the same byte patterns than Windows CRT debug malloc() and free().
1 parent 536a35b commit 4c409be

File tree

6 files changed

+37
-24
lines changed

6 files changed

+37
-24
lines changed

Doc/c-api/memory.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,9 @@ Customize Memory Allocators
440440
441441
Setup hooks to detect bugs in the Python memory allocator functions.
442442
443-
Newly allocated memory is filled with the byte ``0xCB``, freed memory is
444-
filled with the byte ``0xDB``.
443+
Newly allocated memory is filled with the byte ``0xCD`` (``CLEANBYTE``),
444+
freed memory is filled with the byte ``0xDD`` (``DEADBYTE``). Memory blocks
445+
are surrounded by "forbidden bytes" (``FORBIDDENBYTE``: byte ``0xFD``).
445446
446447
Runtime checks:
447448
@@ -471,6 +472,12 @@ Customize Memory Allocators
471472
if the GIL is held when functions of :c:data:`PYMEM_DOMAIN_OBJ` and
472473
:c:data:`PYMEM_DOMAIN_MEM` domains are called.
473474
475+
.. versionchanged:: 3.8.0
476+
Byte patterns ``0xCB`` (``CLEANBYTE``), ``0xDB`` (``DEADBYTE``) and
477+
``0xFB`` (``FORBIDDENBYTE``) have been replaced with ``0xCD``, ``0xDD``
478+
and ``0xFD`` to use the same values than Windows CRT debug ``malloc()``
479+
and ``free()``.
480+
474481
475482
.. _pymalloc:
476483

Include/internal/pycore_pymem.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,20 @@ PyAPI_FUNC(int) _PyMem_SetDefaultAllocator(
160160
pointer value is checked.
161161
162162
The heuristic relies on the debug hooks on Python memory allocators which
163-
fills newly allocated memory with CLEANBYTE (0xCB) and newly freed memory
164-
with DEADBYTE (0xDB). Detect also "untouchable bytes" marked
165-
with FORBIDDENBYTE (0xFB). */
163+
fills newly allocated memory with CLEANBYTE (0xCD) and newly freed memory
164+
with DEADBYTE (0xDD). Detect also "untouchable bytes" marked
165+
with FORBIDDENBYTE (0xFD). */
166166
static inline int _PyMem_IsPtrFreed(void *ptr)
167167
{
168168
uintptr_t value = (uintptr_t)ptr;
169169
#if SIZEOF_VOID_P == 8
170-
return (value == (uintptr_t)0xCBCBCBCBCBCBCBCB
171-
|| value == (uintptr_t)0xDBDBDBDBDBDBDBDB
172-
|| value == (uintptr_t)0xFBFBFBFBFBFBFBFB
173-
);
170+
return (value == (uintptr_t)0xCDCDCDCDCDCDCDCD
171+
|| value == (uintptr_t)0xDDDDDDDDDDDDDDDD
172+
|| value == (uintptr_t)0xFDFDFDFDFDFDFDFD);
174173
#elif SIZEOF_VOID_P == 4
175-
return (value == (uintptr_t)0xCBCBCBCB
176-
|| value == (uintptr_t)0xDBDBDBDB
177-
|| value == (uintptr_t)0xFBFBFBFB);
174+
return (value == (uintptr_t)0xCDCDCDCD
175+
|| value == (uintptr_t)0xDDDDDDDD
176+
|| value == (uintptr_t)0xFDFDFDFD);
178177
#else
179178
# error "unknown pointer size"
180179
#endif

Lib/test/test_capi.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,11 +480,11 @@ def test_buffer_overflow(self):
480480
r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
481481
r" The [0-9] pad bytes at tail={ptr} are not all FORBIDDENBYTE \(0x[0-9a-f]{{2}}\):\n"
482482
r" at tail\+0: 0x78 \*\*\* OUCH\n"
483-
r" at tail\+1: 0xfb\n"
484-
r" at tail\+2: 0xfb\n"
483+
r" at tail\+1: 0xfd\n"
484+
r" at tail\+2: 0xfd\n"
485485
r" .*\n"
486486
r" The block was made by call #[0-9]+ to debug malloc/realloc.\n"
487-
r" Data at p: cb cb cb .*\n"
487+
r" Data at p: cd cd cd .*\n"
488488
r"\n"
489489
r"Enable tracemalloc to get the memory block allocation traceback\n"
490490
r"\n"
@@ -500,7 +500,7 @@ def test_api_misuse(self):
500500
r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n"
501501
r" The [0-9] pad bytes at tail={ptr} are FORBIDDENBYTE, as expected.\n"
502502
r" The block was made by call #[0-9]+ to debug malloc/realloc.\n"
503-
r" Data at p: cb cb cb .*\n"
503+
r" Data at p: cd cd cd .*\n"
504504
r"\n"
505505
r"Enable tracemalloc to get the memory block allocation traceback\n"
506506
r"\n"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Change the value of ``CLEANBYTE``, ``DEADDYTE`` and ``FORBIDDENBYTE`` internal
2+
constants used by debug hooks on Python memory allocators
3+
(:c:func:`PyMem_SetupDebugHooks` function). Byte patterns ``0xCB``, ``0xDB``
4+
and ``0xFB`` have been replaced with ``0xCD``, ``0xDD`` and ``0xFD`` to use the
5+
same values than Windows CRT debug ``malloc()`` and ``free()``.

Objects/object.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,13 +415,12 @@ _Py_BreakPoint(void)
415415
}
416416

417417

418-
/* Heuristic checking if the object memory has been deallocated.
419-
Rely on the debug hooks on Python memory allocators which fills the memory
420-
with DEADBYTE (0xDB) when memory is deallocated.
418+
/* Heuristic checking if the object memory is uninitialized or deallocated.
419+
Rely on the debug hooks on Python memory allocators:
420+
see _PyMem_IsPtrFreed().
421421
422422
The function can be used to prevent segmentation fault on dereferencing
423-
pointers like 0xdbdbdbdbdbdbdbdb. Such pointer is very unlikely to be mapped
424-
in memory. */
423+
pointers like 0xDDDDDDDDDDDDDDDD. */
425424
int
426425
_PyObject_IsFreed(PyObject *op)
427426
{

Objects/obmalloc.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,13 +1915,16 @@ _Py_GetAllocatedBlocks(void)
19151915
/* Special bytes broadcast into debug memory blocks at appropriate times.
19161916
* Strings of these are unlikely to be valid addresses, floats, ints or
19171917
* 7-bit ASCII. If modified, _PyMem_IsPtrFreed() should be updated as well.
1918+
*
1919+
* Byte patterns 0xCB, 0xBB and 0xFB have been replaced with 0xCD, 0xDD and
1920+
* 0xFD to use the same values than Windows CRT debug malloc() and free().
19181921
*/
19191922
#undef CLEANBYTE
19201923
#undef DEADBYTE
19211924
#undef FORBIDDENBYTE
1922-
#define CLEANBYTE 0xCB /* clean (newly allocated) memory */
1923-
#define DEADBYTE 0xDB /* dead (newly freed) memory */
1924-
#define FORBIDDENBYTE 0xFB /* untouchable bytes at each end of a block */
1925+
#define CLEANBYTE 0xCD /* clean (newly allocated) memory */
1926+
#define DEADBYTE 0xDD /* dead (newly freed) memory */
1927+
#define FORBIDDENBYTE 0xFD /* untouchable bytes at each end of a block */
19251928

19261929
static size_t serialno = 0; /* incremented on each debug {m,re}alloc */
19271930

0 commit comments

Comments
 (0)