port: advance VC6 typeobject frontier and preserve regression coverage
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Guard _PyMem_DebugRawRealloc's C89 locals and complete operation order."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1]).read_text()
|
||||
match = re.search(
|
||||
r"\n_PyMem_DebugRawRealloc\(void \*ctx, void \*p, size_t nbytes\)\s*\{(.*?)\n\}",
|
||||
source, re.S,
|
||||
)
|
||||
assert match, "_PyMem_DebugRawRealloc definition not found"
|
||||
body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S)
|
||||
declarations = """
|
||||
debug_alloc_api_t *api;
|
||||
uint8_t *head;
|
||||
uint8_t *data;
|
||||
uint8_t *r;
|
||||
uint8_t *tail;
|
||||
size_t total;
|
||||
size_t original_nbytes;
|
||||
#define ERASED_SIZE 64
|
||||
uint8_t save[2*ERASED_SIZE];
|
||||
#ifdef PYMEM_DEBUG_SERIALNO
|
||||
size_t block_serialno;
|
||||
#endif
|
||||
"""
|
||||
assert body.split()[:len(declarations.split())] == declarations.split(), (
|
||||
"_PyMem_DebugRawRealloc must declare locals without initializers at function entry, "
|
||||
"including block_serialno under PYMEM_DEBUG_SERIALNO"
|
||||
)
|
||||
|
||||
# Keep the ctx cast after the NULL return and the serial-number read after
|
||||
# the overflow guard and tail calculation. Freeze both preprocessor paths,
|
||||
# allocation failure recovery, saved-byte restoration, and growth filling.
|
||||
expected = declarations + """
|
||||
|
||||
if (p == NULL) {
|
||||
return _PyMem_DebugRawAlloc(0, ctx, nbytes);
|
||||
}
|
||||
|
||||
api = (debug_alloc_api_t *)ctx;
|
||||
_PyMem_DebugCheckAddress(__func__, api->api_id, p);
|
||||
|
||||
data = (uint8_t *)p;
|
||||
head = data - 2*SST;
|
||||
original_nbytes = read_size_t(head);
|
||||
if (nbytes > (size_t)PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
total = nbytes + PYMEM_DEBUG_EXTRA_BYTES;
|
||||
|
||||
tail = data + original_nbytes;
|
||||
#ifdef PYMEM_DEBUG_SERIALNO
|
||||
block_serialno = read_size_t(tail + SST);
|
||||
#endif
|
||||
|
||||
if (original_nbytes <= sizeof(save)) {
|
||||
memcpy(save, data, original_nbytes);
|
||||
memset(data - 2 * SST, PYMEM_DEADBYTE,
|
||||
original_nbytes + PYMEM_DEBUG_EXTRA_BYTES);
|
||||
}
|
||||
else {
|
||||
memcpy(save, data, ERASED_SIZE);
|
||||
memset(head, PYMEM_DEADBYTE, ERASED_SIZE + 2 * SST);
|
||||
memcpy(&save[ERASED_SIZE], tail - ERASED_SIZE, ERASED_SIZE);
|
||||
memset(tail - ERASED_SIZE, PYMEM_DEADBYTE,
|
||||
ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST);
|
||||
}
|
||||
|
||||
|
||||
r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, head, total);
|
||||
if (r == NULL) {
|
||||
|
||||
nbytes = original_nbytes;
|
||||
}
|
||||
else {
|
||||
head = r;
|
||||
#ifdef PYMEM_DEBUG_SERIALNO
|
||||
bumpserialno();
|
||||
block_serialno = serialno;
|
||||
#endif
|
||||
}
|
||||
data = head + 2*SST;
|
||||
|
||||
write_size_t(head, nbytes);
|
||||
head[SST] = (uint8_t)api->api_id;
|
||||
memset(head + SST + 1, PYMEM_FORBIDDENBYTE, SST-1);
|
||||
|
||||
tail = data + nbytes;
|
||||
memset(tail, PYMEM_FORBIDDENBYTE, SST);
|
||||
#ifdef PYMEM_DEBUG_SERIALNO
|
||||
write_size_t(tail + SST, block_serialno);
|
||||
#endif
|
||||
|
||||
|
||||
if (original_nbytes <= sizeof(save)) {
|
||||
memcpy(data, save, Py_MIN(nbytes, original_nbytes));
|
||||
}
|
||||
else {
|
||||
size_t i = original_nbytes - ERASED_SIZE;
|
||||
memcpy(data, save, Py_MIN(nbytes, ERASED_SIZE));
|
||||
if (nbytes > i) {
|
||||
memcpy(data + i, &save[ERASED_SIZE],
|
||||
Py_MIN(nbytes - i, ERASED_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
if (r == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nbytes > original_nbytes) {
|
||||
|
||||
memset(data + original_nbytes, PYMEM_CLEANBYTE,
|
||||
nbytes - original_nbytes);
|
||||
}
|
||||
|
||||
return data;"""
|
||||
assert body.split() == expected.split(), (
|
||||
"preserve _PyMem_DebugRawRealloc initialization evaluation points, guards, "
|
||||
"and complete operation/control-flow order"
|
||||
)
|
||||
print("obmalloc _PyMem_DebugRawRealloc C89 declarations and original operation order: PASS")
|
||||
Reference in New Issue
Block a user