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