code wiki / (root) / nx_mmapbal.nx

nx_mmapbal.nx

buildroot/runtime/nx_mmapbal.nx

13804 B342 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind orphan library
docsdependenciesstructsconstsfunctions

about

nx_mmapbal.nx -- STATIC mmap/munmap BALANCE SCANNER over the .nx corpus. WHY THIS EXISTS (measured 2026-07-31, debt 1785515861): the ecosystem's ONLY leak instrument, nx_leak_check, is DYNAMIC and daemon-only -- its `fleet` verb certifies organs that are RUNNING and a LEAK verdict requires LK_MIN_AGE_S=120s of process age. One-shot organs (5365 gates + every CLI organ) live for milliseconds and exit, so they can NEVER appear in a fleet scan and can NEVER reach the age floor. That hole is why nx_gate_verdict.nx -- the D001 base class 150+ organs import -- leaked on EVERY call for ~13 days while every instrument reported healthy. Dynamic and static detection are not redundant here; they cover disjoint halves of the fleet. THE RULE, stated once so it cannot drift: within ONE function, every sys_mmap must be matched by a sys_munmap, UNLESS the signature RETURNS A POINTER -- that is ownership TRANSFER to the caller, not a leak (gv_ctr is the correct exemplar: it returns the counter, which must outlive the call). A function that allocates and returns i64 has no way to hand the memory back, so an unmatched mmap there is a leak BY CONSTRUCTION, provable from the source alone with no runtime sampling. main() IS REPORTED SEPARATELY, NOT CONVICTED: it runs once per process and the kernel reclaims at exit, so an unbalanced mmap in main is a style note, not a defect. Convicting it would bury the real signal (helpers called in loops) under noise -- the ranked-wrong-thing failure. COMMENT LINES ARE SKIPPED so a header that merely MENTIONS sys_mmap cannot fabricate a finding. ⚠ KNOWN LIMITATION -- OWNERSHIP VIA STRUCT FIELD IS INVISIBLE (measured 2026-07-31). mb_owns detects ownership transfer ONLY through a `-> *` RETURN TYPE. A function that hands its allocation to the caller by STORING IT IN AN OUT-PARAM STRUCT FIELD is reported as a leak even though it is correct. PROVEN CASE: nx_opaque_login.olg_ctx_setup_ttl mmaps 5 key buffers and passes 3 to nx_auth_context_init, which does `ctx.opaque_skS_32 = ...` / `ctx.server_ed25519_priv_32 = ...` -- storing the POINTERS, not copying the bytes. Those live for the whole daemon lifetime; freeing them would be a use-after-free on every login and would corrupt the server signing key. CONSEQUENCE: *_init / *_ctx_setup / *_new functions are the FALSE-POSITIVE class of this scanner. A headline count that does not exclude them OVERSTATES the defect. Treat any finding in an initializer as UNPROVEN until the callee is read. Fixing this properly needs callee-aware escape analysis (does the callee store the pointer?), which is a real rung, not a tweak. FAIL-LOUD ON COVERAGE (law L011): prints files_scanned / files_skipped / coverage_complete. A corpus scanner that hides partial coverage presents partial-as-complete, which is the self-ceiling defect. nx_mmapbal scan [dir] walk dir (default buildroot/runtime) for .nx, report unbalanced funcs license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 2 imports · 0 importers

nx_syscalls.nx nx_gate_verdict.nx nx_mmapbal.nx

imports: nx_syscalls.nxnx_gate_verdict.nx

imported by: nobody (leaf or entry point)

structs

none

consts

49const MB_DIRBUF: i64 = 262144
50const MB_FILECAP: i64 = 524288
51const MB_PATHCAP: i64 = 1024
52const MB_DIR_TYPE: i64 = 4
53const MB_NL_C: i64 = 10
54const MB_SLASH_C: i64 = 47
55const MB_SPACE_C: i64 = 32
56const MB_TAB_C: i64 = 9
57const MB_DOT_C: i64 = 46
58const MB_N_C: i64 = 110
59const MB_X_C: i64 = 120
60const MB_WORD: i64 = 8
61const MB_ST_SLOTS: i64 = 8
62const MB_S_FILES: i64 = 0
63const MB_S_FUNCS: i64 = 1
64const MB_S_BAD: i64 = 2
65const MB_S_MAIN: i64 = 3
66const MB_S_SKIP: i64 = 4
67const MB_S_SITES: i64 = 5

functions

69func mb_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
71func mb_streq(a: *u8, b: *u8) -> i64
83func mb_slurp(path: *u8, buf: *u8, cap: i64) -> i64
97func mb_line_end(buf: *u8, s: i64, e: i64) -> i64
106func mb_starts(buf: *u8, s: i64, e: i64, needle: *u8) -> i64
called by 1: mb_is_comment
117func mb_is_comment(buf: *u8, s: i64, e: i64) -> i64
130func mb_count_range(buf: *u8, s: i64, e: i64, needle: *u8) -> i64
148func mb_owns(buf: *u8, s: i64, e: i64) -> i64
157func mb_put_range(buf: *u8, s: i64, e: i64) -> i64
162func mb_is_nx(nm: *u8, n: i64) -> i64
170func mb_join(dir: *u8, nm: *u8, out: *u8) -> i64
182func mb_scan_buf(path: *u8, buf: *u8, n: i64, st: *i64) -> i64
227func main(argc: i64, argv: *i64) -> i64