#!/usr/bin/env python3 """Guard VC6 C89 declaration order in PyFile_OpenCodeObject.""" import sys from pathlib import Path from typing import NoReturn def fail(message: str) -> NoReturn: print(message, file=sys.stderr) raise SystemExit(1) def function_body(source, signature): start = source.find(signature) if start < 0: fail(f"missing function signature: {signature}") brace = source.find("{", start + len(signature)) if brace < 0: fail("missing function body") depth = 0 for end in range(brace, len(source)): if source[end] == "{": depth += 1 elif source[end] == "}": depth -= 1 if depth == 0: return source[brace + 1:end] fail("unterminated function body") path = Path(sys.argv[1]) source = path.read_text(encoding="utf-8") body = function_body(source, "PyFile_OpenCodeObject(PyObject *path)") expected_decl = " Py_OpenCodeHookFunction hook;" if expected_decl not in body: fail("hook must be declared without initializer at function entry") if "Py_OpenCodeHookFunction hook =" in body: fail("hook declaration must not be initialized at declaration") validation = body.find("if (!PyUnicode_Check(path))") assignment = body.find("hook = _PyRuntime.open_code_hook;") if validation < 0 or assignment < 0 or assignment < validation: fail("hook lookup must remain after path validation") if body.find("return NULL;", validation) > assignment: fail("hook lookup must remain after invalid-path early return") print("fileobject open-code hook C89 declaration and validation order: PASS")