#!/usr/bin/env python3 """Guard insert_to_freepool'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"\ninsert_to_freepool\(poolp pool\)\s*\{(.*?)\n\}", source, re.S, ) assert match, "insert_to_freepool definition not found" body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) declarations = """ poolp next; poolp prev; struct arena_object *ao; uint nf; struct arena_object* lastnf; struct arena_object* p; """ assert body.split()[:len(declarations.split())] == declarations.split(), ( "insert_to_freepool must declare all six locals without initializers at function entry" ) # Assignments stay at the original evaluation points, including p inside its # branch. Preserve every assertion, branch, return, and pointer update, as well # as the radix-tree conditional, throughout all four arena-management cases. expected = declarations + """ next = pool->nextpool; prev = pool->prevpool; next->prevpool = prev; prev->nextpool = next; ao = &arenas[pool->arenaindex]; pool->nextpool = ao->freepools; ao->freepools = pool; nf = ao->nfreepools; lastnf = nfp2lasta[nf]; assert((nf == 0 && lastnf == NULL) || (nf > 0 && lastnf != NULL && lastnf->nfreepools == nf && (lastnf->nextarena == NULL || nf < lastnf->nextarena->nfreepools))); if (lastnf == ao) { p = ao->prevarena; nfp2lasta[nf] = (p != NULL && p->nfreepools == nf) ? p : NULL; } ao->nfreepools = ++nf; if (nf == ao->ntotalpools && ao->nextarena != NULL) { assert(ao->prevarena == NULL || ao->prevarena->address != 0); assert(ao ->nextarena == NULL || ao->nextarena->address != 0); if (ao->prevarena == NULL) { usable_arenas = ao->nextarena; assert(usable_arenas == NULL || usable_arenas->address != 0); } else { assert(ao->prevarena->nextarena == ao); ao->prevarena->nextarena = ao->nextarena; } if (ao->nextarena != NULL) { assert(ao->nextarena->prevarena == ao); ao->nextarena->prevarena = ao->prevarena; } ao->nextarena = unused_arena_objects; unused_arena_objects = ao; #if WITH_PYMALLOC_RADIX_TREE arena_map_mark_used(ao->address, 0); #endif _PyObject_Arena.free(_PyObject_Arena.ctx, (void *)ao->address, ARENA_SIZE); ao->address = 0; --narenas_currently_allocated; return; } if (nf == 1) { ao->nextarena = usable_arenas; ao->prevarena = NULL; if (usable_arenas) usable_arenas->prevarena = ao; usable_arenas = ao; assert(usable_arenas->address != 0); if (nfp2lasta[1] == NULL) { nfp2lasta[1] = ao; } return; } if (nfp2lasta[nf] == NULL) { nfp2lasta[nf] = ao; } if (ao == lastnf) { return; } assert(ao->nextarena != NULL); if (ao->prevarena != NULL) { assert(ao->prevarena->nextarena == ao); ao->prevarena->nextarena = ao->nextarena; } else { assert(usable_arenas == ao); usable_arenas = ao->nextarena; } ao->nextarena->prevarena = ao->prevarena; ao->prevarena = lastnf; ao->nextarena = lastnf->nextarena; if (ao->nextarena != NULL) { ao->nextarena->prevarena = ao; } lastnf->nextarena = ao; assert(ao->nextarena == NULL || nf <= ao->nextarena->nfreepools); assert(ao->prevarena == NULL || nf > ao->prevarena->nfreepools); assert(ao->nextarena == NULL || ao->nextarena->prevarena == ao); assert((usable_arenas == ao && ao->prevarena == NULL) || ao->prevarena->nextarena == ao); """ assert body.split() == expected.split(), ( "preserve insert_to_freepool evaluation, assertion, control-flow, and pointer-update order" ) print("obmalloc insert_to_freepool entry declarations and original operation order: PASS")