Files
shadowsocks-libev/tests/alloc_audit/check_steady.py
T
Max Lv 556c1f0696 Add allocation-free C++ AEAD codecs
src/crypto/aead.hpp implements the SIP004/SIP007 AEAD ciphers as value
types: AeadEngine holds the libsodium or Mbed TLS GCM state by value,
AeadTcpEncryptor/AeadTcpDecryptor frame the chunk stream with a fixed
reassembly buffer, and aead_udp_seal/open handle packets. HKDF-SHA1 runs
on stack SHA-1 state instead of Mbed TLS's allocating HMAC API.

The bundled Mbed TLS config now enables MBEDTLS_BLOCK_CIPHER_C, which
keeps the AES context inside mbedtls_gcm_context, so GCM key setup no
longer allocates. That alone saves the C programs two allocations per
connection.

test_crypto_aead_cpp checks HKDF against RFC 5869 and crypto_hkdf, runs
TCP streams and UDP packets between the C and C++ implementations in
both directions for all five AEAD methods, and covers tampering,
framing and salt replay. alloc_steady_crypto_aead runs it under the
malloc counter and requires zero allocations across 600 new
connections and 600 packets (tests/alloc_audit/check_steady.py).

ss_strict_warnings() now applies -Wextra per source file so targets
mixing new C++ with converted C modules keep the latter at -Wall, and
Result gains move assignment.
2026-10-14 22:51:56 +08:00

51 lines
2.0 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Run a test program under the alloc_counter shim and check a steady phase.
The program calls ss::test::alloc_mark() (tests/alloc_audit/alloc_probe.hpp)
before and after the code that must not allocate. This script preloads the
shim, runs the program, and fails unless exactly two marks were recorded and
no allocation happened between them.
Usage: check_steady.py --shim LIB [--max N] -- PROGRAM [ARGS...]
"""
import argparse
import os
from pathlib import Path
import subprocess
import sys
import tempfile
def main():
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("--shim", required=True)
parser.add_argument("--max", type=int, default=0, help="allocations allowed between the marks")
parser.add_argument("command", nargs=argparse.REMAINDER)
args = parser.parse_args()
command = args.command[1:] if args.command[:1] == ["--"] else args.command
if not command:
parser.error("missing program to run")
with tempfile.TemporaryDirectory(prefix="ss-steady-") as temp:
out = Path(temp) / "counts"
env = os.environ.copy()
env["DYLD_INSERT_LIBRARIES" if sys.platform == "darwin" else "LD_PRELOAD"] = str(Path(args.shim).resolve())
env["SS_ALLOC_AUDIT_OUT"] = str(out)
result = subprocess.run(command, env=env)
if result.returncode != 0:
print(f"{command[0]} exited with {result.returncode}")
return 1
lines = out.read_text().splitlines() if out.exists() else []
if len(lines) != 2:
print(f"expected 2 allocation marks, got {len(lines)}")
return 1
before, after = ([int(v) for v in line.split()] for line in lines)
allocations = after[1] - before[1]
print(f"steady phase: {allocations} allocation(s), {after[3] - before[3]} bytes (allowed: {args.max})")
return 0 if allocations <= args.max else 1
if __name__ == "__main__":
sys.exit(main())