code wiki / (root) / nx_gif_boundary_gate_t139.nx

nx_gif_boundary_gate_t139.nx source

↩ module page · 120 lines · 10655 B

1// nx_gif_boundary_gate_t139.nx -- Generates a 4x4 GIF image with a hashed pixel sequence and verifies its SHA-256 digest against expected values. 2import "nx_syscalls.nx" 3import "nx_gate_verdict.nx" 4import "nx_sha256.nx" 5import "nx_gif_decode_t139.nx" 6// append one 3-bit LZW code, LSB-first (GIF bit order); buf must be zeroed (OR-only) 7func gg_putcode(buf: *u8, bitpos: *i64, code: i64) -> i64 { 8 var i: i64=0 9 while i<3 { 10 let bit: i64=(code>>i)&1 11 let bp: i64=bitpos[0] 12 if bit==1 { let by: i64=bp/8; let bo: i64=bp%8; buf[by]=((buf[by] as i64)|(1<<bo)) as u8 } 13 bitpos[0]=bitpos[0]+1 14 i=i+1 15 } 16 return 0 17} 18 19// build a 4x4 GIF89a with a 4-entry GCT (red,green,blue,white) whose pixel-index 20// STORAGE sequence is pixseq[16]; interlaced sets descriptor bit 6. returns length. 21func gg_build_gif(out: *u8, pixseq: *u8, interlaced: i64) -> i64 { 22 out[0]=0x47 as u8; out[1]=0x49 as u8; out[2]=0x46 as u8 23 out[3]=0x38 as u8; out[4]=0x39 as u8; out[5]=0x61 as u8 24 out[6]=4 as u8; out[7]=0 as u8; out[8]=4 as u8; out[9]=0 as u8 25 out[10]=0x81 as u8; out[11]=0 as u8; out[12]=0 as u8 26 out[13]=255 as u8; out[14]=0 as u8; out[15]=0 as u8 27 out[16]=0 as u8; out[17]=255 as u8; out[18]=0 as u8 28 out[19]=0 as u8; out[20]=0 as u8; out[21]=255 as u8 29 out[22]=255 as u8; out[23]=255 as u8; out[24]=255 as u8 30 var o: i64=25 31 out[o]=0x2C as u8 32 out[o+1]=0 as u8; out[o+2]=0 as u8; out[o+3]=0 as u8; out[o+4]=0 as u8 33 out[o+5]=4 as u8; out[o+6]=0 as u8; out[o+7]=4 as u8; out[o+8]=0 as u8 34 if interlaced==1 { out[o+9]=0x40 as u8 } else { out[o+9]=0 as u8 } 35 o=o+10 36 out[o]=2 as u8; o=o+1 37 let lzbuf: *u8=sys_mmap(256) 38 let bitpos: *i64=sys_mmap(8) as *i64 39 bitpos[0]=0 40 var p: i64=0 41 while p<16 { gg_putcode(lzbuf,bitpos,4); gg_putcode(lzbuf,bitpos,pixseq[p] as i64); p=p+1 } 42 gg_putcode(lzbuf,bitpos,5) 43 let nbytes: i64=(bitpos[0]+7)/8 44 out[o]=nbytes as u8; o=o+1 45 var q: i64=0 46 while q<nbytes { out[o]=lzbuf[q]; o=o+1; q=q+1 } 47 out[o]=0 as u8; o=o+1 48 out[o]=0x3B as u8; o=o+1 49 return o 50} 51 52 53func gb_hash(raw: *u8, n: i64, expected: *u8) -> i64 { 54 let wn: i64=sha256_workspace_bytes(); let ws: *u8=gif_own(wn+64) 55 if ws==(0 as *u8) { return 0 } 56 let digest: *u8=((ws as i64)+wn) as *u8 57 var ok: i64=1 58 if sha256_init_workspace(ws,wn)!=0 { ok=0 } else { sha256_update(ws as *Sha256,raw,n); sha256_final(ws as *Sha256,digest) 59 let hex: *u8="0123456789abcdef";var i: i64=0;while i<32 { let v: i64=digest[i] as i64;if hex[v>>4]!=expected[i*2] || hex[v&15]!=expected[i*2+1] { ok=0 } i=i+1 } 60 } 61 if gif_release(ws,wn+64)!=0 { ok=0 } return ok 62} 63func gb_pages() -> i64 { 64 let buf: *u8=gif_own(512);if buf==(0 as *u8) { return 0-1 } 65 let fd: i64=sys_openat_rd("/proc/self/statm");if fd<0 { gif_release(buf,512);return 0-1 } 66 let n: i64=sys_read(fd,buf,511);let rc: i64=sys_close(fd);var value: i64=0;var i: i64=0 67 if n<=0 || rc!=0 { gif_release(buf,512);return 0-1 } 68 while i<n {let c: i64=buf[i] as i64;if c<48 || c>57 {break}value=value*10+c-48;i=i+1} 69 if gif_release(buf,512)!=0 {return 0-1}return value 70} 71func main() -> i64 { 72 let ctr: *i64=gv_ctr();gv_head("GIF bounded first-image decoder; original-pixel differential gate") 73 let raw: *u8=sys_mmap(512);let seq: *u8=sys_mmap(32);var i: i64=0;while i<16{seq[i]=(i/4) as u8;i=i+1} 74 let n: i64=gg_build_gif(raw,seq,0);let wh: *i64=sys_mmap(32) as *i64;let info: *i64=sys_mmap(128) as *i64 75 let rgb: *u8=gif_decode_rgb(raw,n,wh);var ok: i64=0;if rgb!=(0 as *u8){if wh[0]==4 && wh[1]==4{if rgb[0]==(255 as u8) && rgb[1]==(0 as u8) && rgb[2]==(0 as u8) && rgb[15]==(0 as u8) && rgb[16]==(255 as u8){ok=1}}} 76 gv_check("opaque palette KAT",ok,ctr) 77 let gray: *u8=gif_decode(raw,n,wh);ok=0;if gray!=(0 as *u8){if gray[0]==(53 as u8) && gray[5]==(182 as u8) && gray[10]==(18 as u8) && gray[15]==(255 as u8){ok=1}} 78 gv_check("historic gray exact coefficients",ok,ctr);sys_munmap(gray,32) 79 let interraw: *u8=sys_mmap(512);i=0;while i<4{seq[i]=0 as u8;seq[4+i]=2 as u8;seq[8+i]=1 as u8;seq[12+i]=3 as u8;i=i+1} 80 let ni: i64=gg_build_gif(interraw,seq,1);let interrgb: *u8=gif_decode_rgb(interraw,ni,wh);ok=0;if rgb!=(0 as *u8) && interrgb!=(0 as *u8){ok=1;i=0;while i<48{if rgb[i]!=interrgb[i]{ok=0}i=i+1}} 81 gv_check("interlaced wire differs display pixels identical",ok,ctr);sys_munmap(interrgb,64);sys_munmap(rgb,64) 82 var refused: i64=0;i=0;while i<n-1{let p: *u8=gif_decode_rgba_checked(raw,i,wh,info);if p==(0 as *u8){refused=refused+1}else{gif_release(p,wh[0]*wh[1]*4)}i=i+1} 83 gv_check("every incomplete first-image prefix refuses",refused==n-1,ctr) 84 let saved: u8=raw[4];raw[4]=0x30 as u8;var bad: *u8=gif_decode_rgb(raw,n,wh);gv_check("full GIF version signature enforced",bad==(0 as *u8),ctr);raw[4]=saved 85 raw[35]=255 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("mincode255 refused before dictionary init",bad==(0 as *u8),ctr);raw[35]=1 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("mincode1 refused",bad==(0 as *u8),ctr);raw[35]=2 as u8 86 let oldbyte: u8=raw[37];raw[37]=0x3c as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("future dictionary code refused",bad==(0 as *u8),ctr);raw[37]=oldbyte 87 raw[37]=0 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("extra initial literal does not silently overfill image",bad==(0 as *u8),ctr);raw[37]=oldbyte 88 raw[6]=1 as u8;raw[8]=1 as u8;raw[30]=1 as u8;raw[32]=1 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("excess decoded pixels refused not clipped",bad==(0 as *u8),ctr);raw[6]=4 as u8;raw[8]=4 as u8;raw[30]=4 as u8;raw[32]=4 as u8 89 90 let ext: *u8=sys_mmap(512);i=0;while i<25{ext[i]=raw[i];i=i+1}ext[25]=0x21 as u8;ext[26]=0xf9 as u8;ext[27]=4 as u8;ext[28]=5 as u8;ext[29]=5 as u8;ext[30]=0 as u8;ext[31]=0 as u8;ext[32]=0 as u8;i=25;while i<n{ext[i+8]=raw[i];i=i+1} 91 let alpha: *u8=gif_decode_rgba_checked(ext,n+8,wh,info);ok=0;if alpha!=(0 as *u8){if alpha[3]==(0 as u8) && alpha[19]==(255 as u8) && alpha[16]==(0 as u8) && alpha[17]==(255 as u8){ok=1}} 92 gv_check("RGBA exposes first-image transparency without discarding palette colour",ok==1 && info[8]==0 && info[9]==5,ctr);gif_release(alpha,64) 93 bad=gif_decode_rgb(ext,n+8,wh);gv_check("legacy RGB refuses required alpha rather than fabricate black/red matte",bad==(0 as *u8) && wh[0]==0 && wh[1]==0,ctr) 94 ext[32]=1 as u8;bad=gif_decode_rgb(ext,n+8,wh);gv_check("malformed graphics-control terminator refused",bad==(0 as *u8),ctr) 95 raw[6]=6 as u8;raw[8]=6 as u8;raw[26]=1 as u8;raw[28]=1 as u8 96 let rect: *u8=gif_decode_rgba_checked(raw,n,wh,info);gv_check("checked rectangle preserves offsets and logical canvas metadata",rect!=(0 as *u8) && wh[0]==4 && wh[1]==4 && info[10]==1 && info[11]==1 && info[12]==6 && info[13]==6,ctr);gif_release(rect,64) 97 bad=gif_decode_rgb(raw,n,wh);gv_check("legacy RGB refuses unimplemented canvas composition",bad==(0 as *u8),ctr);raw[6]=4 as u8;raw[8]=4 as u8;raw[26]=0 as u8;raw[28]=0 as u8 98 raw[37]=0x2c as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("early EOI with too few pixels refused",bad==(0 as *u8),ctr);raw[37]=oldbyte 99 let lastcode: u8=raw[n-3];raw[n-3]=0 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("missing EOI refused despite enough pixels",bad==(0 as *u8),ctr);raw[n-3]=lastcode 100 let local: *u8=sys_mmap(512);i=0;while i<13{local[i]=raw[i];i=i+1}local[10]=0 as u8;i=0;while i<10{local[13+i]=raw[25+i];i=i+1}local[22]=0x81 as u8;i=0;while i<12{local[23+i]=raw[13+i];i=i+1}i=35;while i<n{local[i]=raw[i];i=i+1} 101 let lr: *u8=gif_decode_rgb(local,n,wh);ok=0;if lr!=(0 as *u8){if lr[0]==(255 as u8) && lr[16]==(255 as u8) && lr[32]==(255 as u8){ok=1}} 102 gv_check("local colour table selected with no global table",ok,ctr);sys_munmap(lr,64) 103 local[22]=0x80 as u8;i=35;while i<n{local[i-6]=local[i];i=i+1}bad=gif_decode_rgb(local,n-6,wh);gv_check("decoded palette index outside table refused",bad==(0 as *u8),ctr) 104 raw[10]=0x87 as u8;bad=gif_decode_rgb(raw,n,wh);gv_check("truncated declared global table refused",bad==(0 as *u8),ctr);raw[10]=0x81 as u8 105 106 let initial_literal: *u8="\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x81\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\xff\xff\xff\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x28\x00\x3b";let literal_rgb: *u8=gif_decode_rgb(initial_literal,40,wh);ok=0;if literal_rgb!=(0 as *u8){if wh[0]==1 && wh[1]==1 && literal_rgb[0]==(255 as u8) && literal_rgb[1]==(0 as u8) && literal_rgb[2]==(0 as u8){ok=1}}gv_check("initial clear is recommendation; literal-first agrees with libvips",ok,ctr);if literal_rgb!=(0 as *u8){literal_rgb[18]=90 as u8;let warm: *u8=sys_mmap(1);gv_check("legacy output retains logical plus16 allocation and historical release",literal_rgb[18]==(90 as u8) && sys_munmap(literal_rgb,19)==0,ctr)} 107 let before: i64=gb_pages();i=0;ok=1;while i<100{let a: *u8=gif_decode_opaque_owned(raw,n,wh,3);if a==(0 as *u8){ok=0}else{if gif_release(a,48)!=0{ok=0}}raw[37]=0x3c as u8;let b: *u8=gif_decode_opaque_owned(raw,n,wh,3);if b!=(0 as *u8){ok=0;gif_release(b,48)}raw[37]=oldbyte;i=i+1}let after: i64=gb_pages() 108 gv_puts("scratch pages before=");gv_num(before);gv_puts(" after=");gv_num(after);gv_puts("\n");gv_check("100 success/failure cycles retain no mapped scratch pages",ok==1 && before>0 && before==after,ctr) 109 let lb: *i64=sys_mmap(16) as *i64;let original: *u8=sys_read_file("/tmp/strut-2d17175184e088f9.gif",lb) 110 ok=0;if original!=(0 as *u8){ok=gb_hash(original,lb[0],"2d17175184e088f93cff9f165644c93f0a9bbfb77757ae154d28e5602b747811")} 111 gv_check("original1339248B identity pinned",ok==1 && lb[0]==1339248,ctr) 112 let rgba: *u8=gif_decode_rgba_checked(original,lb[0],wh,info);ok=0;if rgba!=(0 as *u8){ok=gb_hash(rgba,wh[0]*wh[1]*4,"0ded56809f61d65a9a4d343d10525372240cc9a98a4e49d284209e238697f1f2")} 113 gv_check("original first-frame RGBA equals independent libvips pixel bytes",ok==1 && wh[0]==268 && wh[1]==402,ctr) 114 gv_check("first-frame metadata delay5cs disposal1 offset0 explicit",info[9]==5 && info[14]==1 && info[10]==0 && info[11]==0 && info[15]==GIF_OK_FIRST_IMAGE,ctr);gif_release(rgba,430944) 115 let realrgb: *u8=gif_decode_rgb(original,lb[0],wh);ok=0;if realrgb!=(0 as *u8){ok=gb_hash(realrgb,wh[0]*wh[1]*3,"54196d195b2efe55a593b36c6420868120b3e6426063239b36b00e648d61dc61")} 116 gv_check("original RGB equals independent first-frame RGB",ok,ctr);sys_munmap(realrgb,323224) 117 let realgray: *u8=gif_decode(original,lb[0],wh);ok=0;if realgray!=(0 as *u8){ok=gb_hash(realgray,wh[0]*wh[1],"0da7efd29b40b60fb8acc590580e029440479a2b129bee55c5f31c12ae905923")} 118 gv_check("original gray equals independent RGB plus historic transform",ok,ctr);sys_munmap(realgray,107752) 119 let rc: i64=gv_verdict("GIF-BOUNDARY-GATE",ctr,"first image only; no animation playback/compositing claim");return rc 120}