Commit d1139e04 authored by Tim Peters's avatar Tim Peters

PYMALLOC_DEBUG routines: The "check API family" gimmick was going nowhere

fast, and just cluttered the code.  Get rid of it for now.  If a compelling
case can be made for it, easy to restore it later.
parent 7bf9715a
...@@ -97,14 +97,14 @@ DL_IMPORT(void *) _PyMalloc_Realloc(void *p, size_t nbytes); ...@@ -97,14 +97,14 @@ DL_IMPORT(void *) _PyMalloc_Realloc(void *p, size_t nbytes);
DL_IMPORT(void) _PyMalloc_Free(void *p); DL_IMPORT(void) _PyMalloc_Free(void *p);
#ifdef PYMALLOC_DEBUG #ifdef PYMALLOC_DEBUG
DL_IMPORT(void *) _PyMalloc_DebugMalloc(size_t nbytes, int family); DL_IMPORT(void *) _PyMalloc_DebugMalloc(size_t nbytes);
DL_IMPORT(void *) _PyMalloc_DebugRealloc(void *p, size_t nbytes, int family); DL_IMPORT(void *) _PyMalloc_DebugRealloc(void *p, size_t nbytes);
DL_IMPORT(void) _PyMalloc_DebugFree(void *p, int family); DL_IMPORT(void) _PyMalloc_DebugFree(void *p);
DL_IMPORT(void) _PyMalloc_DebugDumpAddress(const void *p); DL_IMPORT(void) _PyMalloc_DebugDumpAddress(const void *p);
DL_IMPORT(void) _PyMalloc_DebugCheckAddress(const void *p); DL_IMPORT(void) _PyMalloc_DebugCheckAddress(const void *p);
#define _PyMalloc_MALLOC(N) _PyMalloc_DebugMalloc(N, 0) #define _PyMalloc_MALLOC _PyMalloc_DebugMalloc
#define _PyMalloc_REALLOC(P, N) _PyMalloc_DebugRealloc(P, N, 0) #define _PyMalloc_REALLOC _PyMalloc_DebugRealloc
#define _PyMalloc_FREE(P) _PyMalloc_DebugFree(P, 0) #define _PyMalloc_FREE _PyMalloc_DebugFree
#else /* WITH_PYMALLOC && ! PYMALLOC_DEBUG */ #else /* WITH_PYMALLOC && ! PYMALLOC_DEBUG */
#define _PyMalloc_MALLOC _PyMalloc_Malloc #define _PyMalloc_MALLOC _PyMalloc_Malloc
......
...@@ -724,35 +724,13 @@ write4(void *p, ulong n) ...@@ -724,35 +724,13 @@ write4(void *p, ulong n)
q[3] = (uchar)( n & 0xff); q[3] = (uchar)( n & 0xff);
} }
static void
check_family(const void *p, int family)
{
const uchar *q = (const uchar *)p;
int original_family;
char buf[200];
assert(p != NULL);
original_family = (int)*(q-4);
if (family != original_family) {
/* XXX better msg */
PyOS_snprintf(buf, sizeof(buf),
"free or realloc from family #%d called, "
"but block was allocated by family #%d",
family, original_family);
_PyMalloc_DebugDumpAddress(p);
Py_FatalError(buf);
}
}
/* The debug malloc asks for 16 extra bytes and fills them with useful stuff, /* The debug malloc asks for 16 extra bytes and fills them with useful stuff,
here calling the underlying malloc's result p: here calling the underlying malloc's result p:
p[0:4] p[0:4]
Number of bytes originally asked for. 4-byte unsigned integer, Number of bytes originally asked for. 4-byte unsigned integer,
big-endian (easier to read in a memory dump). big-endian (easier to read in a memory dump).
p[4] p[4:8]
The API "family" this malloc call belongs to. XXX todo XXX
p[5:8]
Copies of PYMALLOC_FORBIDDENBYTE. Used to catch under- writes Copies of PYMALLOC_FORBIDDENBYTE. Used to catch under- writes
and reads. and reads.
p[8:8+n] p[8:8+n]
...@@ -773,14 +751,12 @@ p[8+n+4:8+n+8] ...@@ -773,14 +751,12 @@ p[8+n+4:8+n+8]
*/ */
void * void *
_PyMalloc_DebugMalloc(size_t nbytes, int family) _PyMalloc_DebugMalloc(size_t nbytes)
{ {
uchar *p; /* base address of malloc'ed block */ uchar *p; /* base address of malloc'ed block */
uchar *tail; /* p + 8 + nbytes == pointer to tail pad bytes */ uchar *tail; /* p + 8 + nbytes == pointer to tail pad bytes */
size_t total; /* nbytes + 16 */ size_t total; /* nbytes + 16 */
assert(family == 0);
bumpserialno(); bumpserialno();
total = nbytes + 16; total = nbytes + 16;
if (total < nbytes || (total >> 31) > 1) { if (total < nbytes || (total >> 31) > 1) {
...@@ -792,13 +768,12 @@ _PyMalloc_DebugMalloc(size_t nbytes, int family) ...@@ -792,13 +768,12 @@ _PyMalloc_DebugMalloc(size_t nbytes, int family)
return NULL; return NULL;
} }
p = _PyMalloc_Malloc(total); /* XXX derive from family */ p = _PyMalloc_Malloc(total);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
write4(p, nbytes); write4(p, nbytes);
p[4] = (uchar)family; p[4] = p[5] = p[6] = p[7] = PYMALLOC_FORBIDDENBYTE;
p[5] = p[6] = p[7] = PYMALLOC_FORBIDDENBYTE;
if (nbytes > 0) if (nbytes > 0)
memset(p+8, PYMALLOC_CLEANBYTE, nbytes); memset(p+8, PYMALLOC_CLEANBYTE, nbytes);
...@@ -816,38 +791,31 @@ _PyMalloc_DebugMalloc(size_t nbytes, int family) ...@@ -816,38 +791,31 @@ _PyMalloc_DebugMalloc(size_t nbytes, int family)
Then calls the underlying free. Then calls the underlying free.
*/ */
void void
_PyMalloc_DebugFree(void *p, int family) _PyMalloc_DebugFree(void *p)
{ {
uchar *q = (uchar *)p; uchar *q = (uchar *)p;
size_t nbytes; size_t nbytes;
assert(family == 0);
if (p == NULL) if (p == NULL)
return; return;
check_family(p, family);
_PyMalloc_DebugCheckAddress(p); _PyMalloc_DebugCheckAddress(p);
nbytes = read4(q-8); nbytes = read4(q-8);
if (nbytes > 0) if (nbytes > 0)
memset(q, PYMALLOC_DEADBYTE, nbytes); memset(q, PYMALLOC_DEADBYTE, nbytes);
_PyMalloc_Free(q-8); /* XXX derive from family */ _PyMalloc_Free(q-8);
} }
void * void *
_PyMalloc_DebugRealloc(void *p, size_t nbytes, int family) _PyMalloc_DebugRealloc(void *p, size_t nbytes)
{ {
uchar *q = (uchar *)p; uchar *q = (uchar *)p;
size_t original_nbytes; size_t original_nbytes;
void *fresh; /* new memory block, if needed */ void *fresh; /* new memory block, if needed */
assert(family == 0);
if (p == NULL) if (p == NULL)
return _PyMalloc_DebugMalloc(nbytes, family); return _PyMalloc_DebugMalloc(nbytes);
check_family(p, family);
_PyMalloc_DebugCheckAddress(p); _PyMalloc_DebugCheckAddress(p);
original_nbytes = read4(q-8); original_nbytes = read4(q-8);
if (nbytes == original_nbytes) { if (nbytes == original_nbytes) {
/* note that this case is likely to be common due to the /* note that this case is likely to be common due to the
...@@ -864,19 +832,19 @@ _PyMalloc_DebugRealloc(void *p, size_t nbytes, int family) ...@@ -864,19 +832,19 @@ _PyMalloc_DebugRealloc(void *p, size_t nbytes, int family)
bumpserialno(); bumpserialno();
write4(q-8, nbytes); write4(q-8, nbytes);
/* kill the excess bytes plus the trailing 8 pad bytes */ /* kill the excess bytes plus the trailing 8 pad bytes */
memset(q + nbytes, PYMALLOC_DEADBYTE, excess + 8);
q += nbytes; q += nbytes;
q[0] = q[1] = q[2] = q[3] = PYMALLOC_FORBIDDENBYTE; q[0] = q[1] = q[2] = q[3] = PYMALLOC_FORBIDDENBYTE;
write4(q+4, serialno); write4(q+4, serialno);
memset(q+8, PYMALLOC_DEADBYTE, excess);
return p; return p;
} }
/* More memory is needed: get it, copy over the first original_nbytes /* More memory is needed: get it, copy over the first original_nbytes
of the original data, and free the original memory. */ of the original data, and free the original memory. */
fresh = _PyMalloc_DebugMalloc(nbytes, family); fresh = _PyMalloc_DebugMalloc(nbytes);
if (fresh != NULL && original_nbytes > 0) if (fresh != NULL && original_nbytes > 0)
memcpy(fresh, p, original_nbytes); memcpy(fresh, p, original_nbytes);
_PyMalloc_DebugFree(p, family); _PyMalloc_DebugFree(p);
return fresh; return fresh;
} }
...@@ -884,32 +852,37 @@ void ...@@ -884,32 +852,37 @@ void
_PyMalloc_DebugCheckAddress(const void *p) _PyMalloc_DebugCheckAddress(const void *p)
{ {
const uchar *q = (const uchar *)p; const uchar *q = (const uchar *)p;
char *msg = NULL; char *msg;
int i;
if (p == NULL) if (p == NULL) {
msg = "didn't expect a NULL pointer"; msg = "didn't expect a NULL pointer";
goto error;
}
else if (*(q-3) != PYMALLOC_FORBIDDENBYTE || for (i = 4; i >= 1; --i) {
*(q-2) != PYMALLOC_FORBIDDENBYTE || if (*(q-i) != PYMALLOC_FORBIDDENBYTE) {
*(q-1) != PYMALLOC_FORBIDDENBYTE)
msg = "bad leading pad byte"; msg = "bad leading pad byte";
goto error;
}
}
else { {
const ulong nbytes = read4(q-8); const ulong nbytes = read4(q-8);
const uchar *tail = q + nbytes; const uchar *tail = q + nbytes;
int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
if (tail[i] != PYMALLOC_FORBIDDENBYTE) { if (tail[i] != PYMALLOC_FORBIDDENBYTE) {
msg = "bad trailing pad byte"; msg = "bad trailing pad byte";
break; goto error;
} }
} }
} }
if (msg != NULL) { return;
error:
_PyMalloc_DebugDumpAddress(p); _PyMalloc_DebugDumpAddress(p);
Py_FatalError(msg); Py_FatalError(msg);
}
} }
void void
...@@ -918,6 +891,7 @@ _PyMalloc_DebugDumpAddress(const void *p) ...@@ -918,6 +891,7 @@ _PyMalloc_DebugDumpAddress(const void *p)
const uchar *q = (const uchar *)p; const uchar *q = (const uchar *)p;
const uchar *tail; const uchar *tail;
ulong nbytes, serial; ulong nbytes, serial;
int i;
fprintf(stderr, "Debug memory block at address p=%p:\n", p); fprintf(stderr, "Debug memory block at address p=%p:\n", p);
if (p == NULL) if (p == NULL)
...@@ -925,22 +899,21 @@ _PyMalloc_DebugDumpAddress(const void *p) ...@@ -925,22 +899,21 @@ _PyMalloc_DebugDumpAddress(const void *p)
nbytes = read4(q-8); nbytes = read4(q-8);
fprintf(stderr, " %lu bytes originally allocated\n", nbytes); fprintf(stderr, " %lu bytes originally allocated\n", nbytes);
fprintf(stderr, " from API family #%d\n", *(q-4));
/* In case this is nuts, check the pad bytes before trying to read up /* In case this is nuts, check the pad bytes before trying to read up
the serial number (the address deref could blow up). */ the serial number (the address deref could blow up). */
fputs(" the 3 pad bytes at p-3 are ", stderr); fputs(" the 4 pad bytes at p-4 are ", stderr);
if (*(q-3) == PYMALLOC_FORBIDDENBYTE && if (*(q-4) == PYMALLOC_FORBIDDENBYTE &&
*(q-3) == PYMALLOC_FORBIDDENBYTE &&
*(q-2) == PYMALLOC_FORBIDDENBYTE && *(q-2) == PYMALLOC_FORBIDDENBYTE &&
*(q-1) == PYMALLOC_FORBIDDENBYTE) { *(q-1) == PYMALLOC_FORBIDDENBYTE) {
fputs("PYMALLOC_FORBIDDENBYTE, as expected\n", stderr); fputs("PYMALLOC_FORBIDDENBYTE, as expected\n", stderr);
} }
else { else {
int i;
fprintf(stderr, "not all PYMALLOC_FORBIDDENBYTE (0x%02x):\n", fprintf(stderr, "not all PYMALLOC_FORBIDDENBYTE (0x%02x):\n",
PYMALLOC_FORBIDDENBYTE); PYMALLOC_FORBIDDENBYTE);
for (i = 3; i >= 1; --i) { for (i = 4; i >= 1; --i) {
const uchar byte = *(q-i); const uchar byte = *(q-i);
fprintf(stderr, " at p-%d: 0x%02x", i, byte); fprintf(stderr, " at p-%d: 0x%02x", i, byte);
if (byte != PYMALLOC_FORBIDDENBYTE) if (byte != PYMALLOC_FORBIDDENBYTE)
...@@ -958,7 +931,6 @@ _PyMalloc_DebugDumpAddress(const void *p) ...@@ -958,7 +931,6 @@ _PyMalloc_DebugDumpAddress(const void *p)
fputs("PYMALLOC_FORBIDDENBYTE, as expected\n", stderr); fputs("PYMALLOC_FORBIDDENBYTE, as expected\n", stderr);
} }
else { else {
int i;
fprintf(stderr, "not all PYMALLOC_FORBIDDENBYTE (0x%02x):\n", fprintf(stderr, "not all PYMALLOC_FORBIDDENBYTE (0x%02x):\n",
PYMALLOC_FORBIDDENBYTE); PYMALLOC_FORBIDDENBYTE);
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment