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}