46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
#!/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")
|