#!/usr/bin/env python3 """Guard pymalloc_free'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"\npymalloc_free\(void \*ctx, void \*p\)\s*\{(.*?)\n\}", source, re.S, ) assert match, "pymalloc_free definition not found" body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) declarations = """ poolp pool; block *lastfree; """ assert body.split()[:len(declarations.split())] == declarations.split(), ( "pymalloc_free must declare pool and lastfree without initializers at function entry" ) # Evaluate POOL_ADDR only after the Valgrind early return, and read freeblock # only after the address-range check and refcount assertion. Preserve all # free-list writes, refcount updates, branches, helper calls, and returns. expected = declarations + """ assert(p != NULL); #ifdef WITH_VALGRIND if (UNLIKELY(running_on_valgrind > 0)) { return 0; } #endif pool = POOL_ADDR(p); if (UNLIKELY(!address_in_range(p, pool))) { return 0; } assert(pool->ref.count > 0); lastfree = pool->freeblock; *(block **)p = lastfree; pool->freeblock = (block *)p; pool->ref.count--; if (UNLIKELY(lastfree == NULL)) { insert_to_usedpool(pool); return 1; } if (LIKELY(pool->ref.count != 0)) { return 1; } insert_to_freepool(pool); return 1; """ assert body.split() == expected.split(), ( "preserve pymalloc_free initialization, evaluation, and control-flow order" ) print("obmalloc pymalloc_free entry declarations and original operation order: PASS")