code wiki / _hdl_build / nx_lora_screen_lib.nx
nx_lora_screen_lib.nx source
↩ module page · 250 lines · 10609 B
1// nx_lora_screen_lib.nx -- LIB: the G16 lc_screen judgement (static contamination/integrity screen on an acquired
2// LoRA or checkpoint FILE, before it may enter elara_loras.txt or the served model path). The lib carries ALL the
3// judgement so nx_lora_screen_gate proves it in-process against crafted fixtures (the lib+program split that makes
4// a gate honest); runtime/nx_lora_screen.nx is the thin main.
5//
6// WHAT IT JUDGES (.safetensors): the 8-byte LE header length, the JSON header's declared data_offsets, and whether
7// those extents exactly tile the file's data region. A file whose declared sizes disagree with its bytes is either
8// truncated, forged, or carrying an undeclared payload -- each flag is NAMED with its values printed.
9// DECLARED IMPRECISION (so the next reader does not trust this as exact): the tiling check compares sum(extents)
10// and max(end) to the region -- a gap and an overlap of EQUAL size cancel and pass; full interval-overlap proof
11// is deliberately not implemented (sort-free single pass). Every real-world serializer writes tensors back to
12// back, which sum==max_end==region does prove.
13// .ckpt/.pt/.pth/.bin/.pkl are REFUSED OUTRIGHT: pickled checkpoints execute arbitrary code on load (CWE-502);
14// the remedy is to obtain a .safetensors export. This is a refusal, not a flag -- there is no safe way to screen
15// a pickle by reading it.
16// verdicts (returned by lc_screen, printed with values): 0 CLEAN | 1 FLAGGED | 3 UNPROVEN (unreadable or a format
17// this screen cannot judge -- abstain, never acquit) | 4 REFUSED-pickle
18// license_tier: ORIGINAL
19import "nx_syscalls.nx"
20
21const LC_HDR_CAP: i64 = 16777216 // 16 MiB header ceiling: real safetensors headers are far below this; a bigger one is FLAGGED, never silently truncated
22const LC_META_EXCERPT: i64 = 700 // bytes of __metadata__ printed (trigger words live here)
23
24func lc_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
25func lc_lc(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c }
26func lc_put(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
27func lc_num(v: i64) -> i64 {
28 var m: i64=v
29 if m<0 { lc_put("-" as *u8); m=0-m }
30 let t: *u8=sys_mmap(28)
31 var k: i64=0
32 if m==0 { t[0]=48 as u8; k=1 }
33 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
34 let b: *u8=sys_mmap(28)
35 var j: i64=0
36 while j<k { b[j]=t[k-1-j]; j=j+1 }
37 sys_write(1,b,k)
38 return 0
39}
40
41// does path end (case-insensitively) with ext?
42func lc_ends_ci(path: *u8, ext: *u8) -> i64 {
43 let pl: i64 = lc_slen(path)
44 let el: i64 = lc_slen(ext)
45 if el>pl { return 0 }
46 var i: i64=0
47 while i<el {
48 if lc_lc(path[pl-el+i] as i64)!=lc_lc(ext[i] as i64) { return 0 }
49 i=i+1
50 }
51 return 1
52}
53
54// 1 = safetensors, 4 = pickle-class (refuse), 0 = unknown (abstain)
55func lc_class(path: *u8) -> i64 {
56 if lc_ends_ci(path, ".safetensors" as *u8)==1 { return 1 }
57 if lc_ends_ci(path, ".ckpt" as *u8)==1 { return 4 }
58 if lc_ends_ci(path, ".pt" as *u8)==1 { return 4 }
59 if lc_ends_ci(path, ".pth" as *u8)==1 { return 4 }
60 if lc_ends_ci(path, ".bin" as *u8)==1 { return 4 }
61 if lc_ends_ci(path, ".pkl" as *u8)==1 { return 4 }
62 if lc_ends_ci(path, ".pickle" as *u8)==1 { return 4 }
63 return 0
64}
65
66func lc_u64le(b: *u8) -> i64 {
67 var v: i64=0
68 var i: i64=7
69 while i>=0 { v = v*256 + (b[i] as i64); i=i-1 }
70 return v
71}
72
73func lc_find(buf: *u8, n: i64, from: i64, needle: *u8) -> i64 {
74 let m: i64 = lc_slen(needle)
75 if m==0 { return 0-1 }
76 var i: i64=from
77 while i+m<=n {
78 var j: i64=0
79 var ok: i64=1
80 while j<m { if buf[i+j]!=needle[j] { ok=0; j=m } else { j=j+1 } }
81 if ok==1 { return i }
82 i=i+1
83 }
84 return 0-1
85}
86
87func lc_parse_uint(buf: *u8, n: i64, pos: i64) -> i64 {
88 var v: i64=0
89 var i: i64=pos
90 var any: i64=0
91 var go: i64=1
92 while go==1 {
93 if i>=n { go=0 } else {
94 let c: i64 = buf[i] as i64
95 if c>=48 { if c<=57 { v=v*10+(c-48); any=1; i=i+1 } else { go=0 } } else { go=0 }
96 }
97 }
98 if any==0 { return 0-1 }
99 return v
100}
101
102// scan every "data_offsets":[a,b] in json[0..n). Fills res: [0]=sum(b-a) [1]=max(b) [2]=bad pairs (b<a or parse fail) [3]=tensor count.
103func lc_scan_offsets(json: *u8, n: i64, res: *i64) -> i64 {
104 res[0]=0
105 res[1]=0
106 res[2]=0
107 res[3]=0
108 let mk: *u8 = "\"data_offsets\":[" as *u8
109 let ml: i64 = lc_slen(mk)
110 var from: i64=0
111 var go: i64=1
112 while go==1 {
113 let p: i64 = lc_find(json, n, from, mk)
114 if p<0 { go=0 } else {
115 let a: i64 = lc_parse_uint(json, n, p+ml)
116 var q: i64=p+ml
117 var go2: i64=1
118 var comma: i64=0-1
119 while go2==1 {
120 if q>=n { go2=0 } else {
121 let c: i64 = json[q] as i64
122 if c==44 { comma=q; go2=0 } else { if c==93 { go2=0 } else { q=q+1 } }
123 }
124 }
125 var b: i64=0-1
126 if comma>=0 { b = lc_parse_uint(json, n, comma+1) }
127 res[3]=res[3]+1
128 if a<0 { res[2]=res[2]+1 } else { if b<a { res[2]=res[2]+1 } else {
129 res[0]=res[0]+(b-a)
130 if b>res[1] { res[1]=b }
131 } }
132 from=p+ml
133 }
134 }
135 return res[3]
136}
137
138// print a bounded excerpt of __metadata__ (trigger words, tags). Prints metadata=NONE when absent.
139func lc_metadata_print(json: *u8, n: i64) -> i64 {
140 let p: i64 = lc_find(json, n, 0, "\"__metadata__\"" as *u8)
141 if p<0 { lc_put("metadata=NONE\n" as *u8); return 0 }
142 lc_put("metadata=" as *u8)
143 var i: i64=p
144 var shown: i64=0
145 var depth: i64=0
146 var started: i64=0
147 var go: i64=1
148 let one: *u8 = sys_mmap(8)
149 while go==1 {
150 if i>=n { go=0 } else { if shown>=LC_META_EXCERPT { lc_put("...(truncated excerpt)" as *u8); go=0 } else {
151 let c: i64 = json[i] as i64
152 if c==123 { depth=depth+1; started=1 }
153 if started==1 {
154 one[0]=c as u8
155 sys_write(1, one, 1)
156 shown=shown+1
157 }
158 if c==125 { depth=depth-1; if started==1 { if depth<=0 { go=0 } } }
159 i=i+1
160 } }
161 }
162 lc_put("\n" as *u8)
163 return 0
164}
165
166// THE SCREEN. Returns 0 CLEAN | 1 FLAGGED | 3 UNPROVEN | 4 REFUSED-pickle. Prints values, not just verdicts.
167func lc_screen(path: *u8) -> i64 {
168 let cls: i64 = lc_class(path)
169 if cls==4 {
170 lc_put("REFUSED-PICKLE path=" as *u8); lc_put(path)
171 lc_put(" rule=CWE-502 -- a pickled checkpoint executes arbitrary code on load; there is no safe read-side screen. Obtain a .safetensors export of this artifact instead.\n" as *u8)
172 return 4
173 }
174 if cls==0 {
175 lc_put("UNPROVEN unknown-extension path=" as *u8); lc_put(path)
176 lc_put(" -- only .safetensors is screened today (a .gguf screen is a separate parser, not yet built); abstaining rather than acquitting\n" as *u8)
177 return 3
178 }
179 let fd: i64 = sys_openat_rd(path)
180 if fd<0 { lc_put("UNPROVEN unreadable path=" as *u8); lc_put(path); lc_put("\n" as *u8); return 3 }
181 let fsize: i64 = sys_lseek(fd, 0, 2)
182 sys_lseek(fd, 0, 0)
183 if fsize<8 {
184 sys_close(fd)
185 lc_put("FLAG SHORTER-THAN-HEADER-LENGTH-FIELD file_bytes=" as *u8); lc_num(fsize); lc_put("\n" as *u8)
186 lc_put("verdict=FLAGGED flags=1\n" as *u8)
187 return 1
188 }
189 let lenb: *u8 = sys_mmap(16)
190 var got: i64=0
191 while got<8 { let r: i64 = sys_read(fd, (lenb as i64 + got) as *u8, 8-got); if r<=0 { got=8 } else { got=got+r } }
192 let hlen: i64 = lc_u64le(lenb)
193 lc_put("file_bytes=" as *u8); lc_num(fsize); lc_put(" header_bytes=" as *u8); lc_num(hlen); lc_put("\n" as *u8)
194 var flags: i64=0
195 if hlen<2 {
196 sys_close(fd)
197 lc_put("FLAG HEADER-IMPOSSIBLY-SMALL header_bytes=" as *u8); lc_num(hlen); lc_put("\n" as *u8)
198 lc_put("verdict=FLAGGED flags=1\n" as *u8)
199 return 1
200 }
201 if hlen>fsize-8 {
202 sys_close(fd)
203 lc_put("FLAG HEADER-EXCEEDS-FILE header_bytes=" as *u8); lc_num(hlen); lc_put(" file_bytes=" as *u8); lc_num(fsize)
204 lc_put(" -- truncated download or forged length field\n" as *u8)
205 lc_put("verdict=FLAGGED flags=1\n" as *u8)
206 return 1
207 }
208 if hlen>LC_HDR_CAP {
209 sys_close(fd)
210 lc_put("FLAG HEADER-OVERSIZE header_bytes=" as *u8); lc_num(hlen); lc_put(" cap=" as *u8); lc_num(LC_HDR_CAP)
211 lc_put(" -- refusing to parse rather than silently truncate the header\n" as *u8)
212 lc_put("verdict=FLAGGED flags=1\n" as *u8)
213 return 1
214 }
215 let json: *u8 = sys_mmap(hlen+1)
216 got=0
217 var rbad: i64=0
218 while got<hlen { let r: i64 = sys_read(fd, (json as i64 + got) as *u8, hlen-got); if r<=0 { rbad=1; got=hlen } else { got=got+r } }
219 sys_close(fd)
220 if rbad==1 { lc_put("UNPROVEN short-read-of-declared-header\n" as *u8); return 3 }
221 let region: i64 = fsize-8-hlen
222 let res: *i64 = (sys_mmap(64)) as *i64
223 lc_scan_offsets(json, hlen, res)
224 lc_put("data_region_bytes=" as *u8); lc_num(region)
225 lc_put(" tensors=" as *u8); lc_num(res[3])
226 lc_put(" declared_sum=" as *u8); lc_num(res[0])
227 lc_put(" declared_max_end=" as *u8); lc_num(res[1])
228 lc_put("\n" as *u8)
229 lc_metadata_print(json, hlen)
230 if res[3]==0 { flags=flags+1; lc_put("FLAG NO-TENSORS -- a weights file declaring zero tensors is not a weights file\n" as *u8) }
231 if res[2]>0 { flags=flags+1; lc_put("FLAG NEGATIVE-OR-UNPARSEABLE-EXTENT pairs=" as *u8); lc_num(res[2]); lc_put("\n" as *u8) }
232 if res[1]>region {
233 flags=flags+1
234 lc_put("FLAG DECLARED-EXCEEDS-FILE declared_max_end=" as *u8); lc_num(res[1]); lc_put(" data_region_bytes=" as *u8); lc_num(region)
235 lc_put(" -- truncated body or forged header\n" as *u8)
236 }
237 if res[1]<region {
238 flags=flags+1
239 lc_put("FLAG TRAILING-PAYLOAD undeclared_bytes=" as *u8); lc_num(region-res[1])
240 lc_put(" -- bytes after the declared tensor data that no tensor accounts for\n" as *u8)
241 }
242 if res[3]>0 { if res[0]!=res[1] {
243 flags=flags+1
244 lc_put("FLAG GAP-OR-OVERLAP declared_sum=" as *u8); lc_num(res[0]); lc_put(" declared_max_end=" as *u8); lc_num(res[1])
245 lc_put(" -- extents do not tile the region: hidden non-tensor payload or overlapping tensors\n" as *u8)
246 } }
247 if flags==0 { lc_put("verdict=CLEAN flags=0\n" as *u8); return 0 }
248 lc_put("verdict=FLAGGED flags=" as *u8); lc_num(flags); lc_put("\n" as *u8)
249 return 1
250}