code wiki / (root) / nx_build_canon_input_lib.nx

nx_build_canon_input_lib.nx source

↩ module page · 143 lines · 4731 B

1// Pure build admission input validation. No allocation, I/O, or hardware writes. 2// Callers own buffer lengths. Hash-row len is a byte count, not an end offset. 3const BCI_INVALID: i64 = 0 - 1 4const BCI_SHA_HEX: i64 = 64 5const BCI_SPACE: i64 = 32 6const BCI_LF: i64 = 10 7const BCI_CR: i64 = 13 8const BCI_COMMENT: i64 = 35 9const BCI_FREEZE: i64 = 33 10const BCI_SLASH: i64 = 47 11const BCI_DOT: i64 = 46 12const BCI_DASH: i64 = 45 13const BCI_UNDERSCORE: i64 = 95 14const BCI_ZERO: i64 = 48 15const BCI_NINE: i64 = 57 16const BCI_LOWER_A: i64 = 97 17const BCI_LOWER_F: i64 = 102 18const BCI_LOWER_Z: i64 = 122 19const BCI_UPPER_A: i64 = 65 20const BCI_UPPER_Z: i64 = 90 21const BCI_DECIMAL_BASE: i64 = 10 22const BCI_I64_MAX: i64 = 9223372036854775807 23 24func bci_resource_allowed(rc: i64) -> i64 { 25 if rc == 0 { return 1 } 26 return 0 27} 28 29func bci_path_char(c: i64) -> i64 { 30 if c >= BCI_ZERO { if c <= BCI_NINE { return 1 } } 31 if c >= BCI_LOWER_A { if c <= BCI_LOWER_Z { return 1 } } 32 if c >= BCI_UPPER_A { if c <= BCI_UPPER_Z { return 1 } } 33 if c == BCI_DOT { return 1 } 34 if c == BCI_DASH { return 1 } 35 if c == BCI_UNDERSCORE { return 1 } 36 return 0 37} 38 39// Reject absolute paths, empty components, dot components, controls and backslashes. 40// max_path_len excludes the caller's prefix and trailing NUL. 41func bci_relative_path(buf: *u8, start: i64, len: i64, max_path_len: i64) -> i64 { 42 if (buf as i64) == 0 { return 0 } 43 if start < 0 { return 0 } 44 if len <= 0 { return 0 } 45 if len > max_path_len { return 0 } 46 if start > BCI_I64_MAX - len { return 0 } 47 var i: i64 = 0 48 var component: i64 = 0 49 var dots: i64 = 0 50 while i < len { 51 let c: i64 = buf[start+i] as i64 52 if c == BCI_SLASH { 53 if component == 0 { return 0 } 54 if component == dots { if component <= 2 { return 0 } } 55 component = 0 56 dots = 0 57 } else { 58 if bci_path_char(c) == 0 { return 0 } 59 component = component + 1 60 if c == BCI_DOT { dots = dots + 1 } 61 } 62 i = i + 1 63 } 64 if component == 0 { return 0 } 65 if component == dots { if component <= 2 { return 0 } } 66 return 1 67} 68 69func bci_conf_rows(buf: *u8, len: i64, max_path_len: i64) -> i64 { 70 if (buf as i64) == 0 { return BCI_INVALID } 71 if len <= 0 { return BCI_INVALID } 72 if max_path_len <= 0 { return BCI_INVALID } 73 var rows: i64 = 0 74 var p: i64 = 0 75 while p < len { 76 var e: i64 = p 77 var scan: i64 = 1 78 while scan == 1 { 79 if e >= len { scan = 0 } else { 80 if buf[e] == (BCI_LF as u8) { scan = 0 } else { e = e + 1 } 81 } 82 } 83 var end: i64 = e 84 if end > p { if buf[end-1] == (BCI_CR as u8) { end = end - 1 } } 85 if end > p { 86 if buf[p] != (BCI_COMMENT as u8) { 87 var start: i64 = p 88 if buf[start] == (BCI_FREEZE as u8) { start = start + 1 } 89 if bci_relative_path(buf, start, end-start, max_path_len) != 1 { return BCI_INVALID } 90 rows = rows + 1 91 } 92 } 93 if e == len { p = len } else { p = e + 1 } 94 } 95 if rows == 0 { return BCI_INVALID } 96 return rows 97} 98 99func bci_hash_row(buf: *u8, start: i64, len: i64) -> i64 { 100 if (buf as i64) == 0 { return 0 } 101 if start < 0 { return 0 } 102 if len <= BCI_SHA_HEX { return 0 } 103 if start > BCI_I64_MAX - len { return 0 } 104 var end: i64 = start + len 105 if buf[end-1] == (BCI_LF as u8) { end = end - 1 } 106 if end > start { if buf[end-1] == (BCI_CR as u8) { end = end - 1 } } 107 if end - start <= BCI_SHA_HEX { return 0 } 108 var i: i64 = start 109 while i < start + BCI_SHA_HEX { 110 let c: i64 = buf[i] as i64 111 var hex: i64 = 0 112 if c >= BCI_ZERO { if c <= BCI_NINE { hex = 1 } } 113 if c >= BCI_LOWER_A { if c <= BCI_LOWER_F { hex = 1 } } 114 if hex == 0 { return 0 } 115 i = i + 1 116 } 117 if buf[i] != (BCI_SPACE as u8) { return 0 } 118 i = i + 1 119 var digits: i64 = 0 120 var value: i64 = 0 121 var scan: i64 = 1 122 while scan == 1 { 123 if i >= end { scan = 0 } else { 124 let c: i64 = buf[i] as i64 125 if c == BCI_SPACE { scan = 0 } else { 126 if c < BCI_ZERO { return 0 } 127 if c > BCI_NINE { return 0 } 128 let digit: i64 = c - BCI_ZERO 129 if value > (BCI_I64_MAX - digit) / BCI_DECIMAL_BASE { return 0 } 130 value = value * BCI_DECIMAL_BASE + digit 131 digits = digits + 1 132 i = i + 1 133 } 134 } 135 } 136 if digits == 0 { return 0 } 137 if value <= 0 { return 0 } 138 if i >= end { return 0 } 139 i = i + 1 140 return bci_relative_path(buf, i, end-i, end-i) 141} 142 143