@clear-capabilities/agentic-security-scanner 0.79.0 → 0.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/178.index.js +1 -1
- package/dist/333.index.js +283 -0
- package/dist/384.index.js +1 -1
- package/dist/637.index.js +1 -1
- package/dist/838.index.js +1 -1
- package/dist/985.index.js +90 -1
- package/dist/agentic-security.mjs +83 -83
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +6 -4
- package/src/.agentic-security/findings.json +104638 -0
- package/src/.agentic-security/last-scan.json +104638 -0
- package/src/.agentic-security/last-scan.json.sig +1 -0
- package/src/.agentic-security/scan-history.json +12562 -0
- package/src/.agentic-security/streak.json +21 -0
- package/src/dataflow/.agentic-security/findings.json +6086 -0
- package/src/dataflow/.agentic-security/last-scan.json +6086 -0
- package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
- package/src/dataflow/.agentic-security/scan-history.json +250 -0
- package/src/dataflow/.agentic-security/streak.json +21 -0
- package/src/dataflow/cross-service-taint.js +201 -0
- package/src/dataflow/formal-verify.js +204 -0
- package/src/dataflow/ifds-precise.js +222 -0
- package/src/dataflow/k2-summary-cache.js +153 -0
- package/src/dataflow/lib-taint-summaries.js +198 -0
- package/src/dataflow/privacy-taint.js +205 -0
- package/src/dataflow/smt-feasibility.js +189 -0
- package/src/engine.js +784 -127
- package/src/ir/.agentic-security/findings.json +4011 -0
- package/src/ir/.agentic-security/last-scan.json +4011 -0
- package/src/ir/.agentic-security/last-scan.json.sig +1 -0
- package/src/ir/.agentic-security/scan-history.json +193 -0
- package/src/ir/.agentic-security/streak.json +20 -0
- package/src/ir/cpp-preprocessor.js +142 -0
- package/src/ir/csharp-ir.js +604 -0
- package/src/ir/universal-ir.js +403 -0
- package/src/mcp/.agentic-security/findings.json +8632 -0
- package/src/mcp/.agentic-security/last-scan.json +8632 -0
- package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
- package/src/mcp/.agentic-security/scan-history.json +143 -0
- package/src/mcp/.agentic-security/streak.json +20 -0
- package/src/mcp/tools.js +90 -1
- package/src/posture/.agentic-security/findings.json +64004 -0
- package/src/posture/.agentic-security/last-scan.json +64004 -0
- package/src/posture/.agentic-security/last-scan.json.sig +1 -0
- package/src/posture/.agentic-security/scan-history.json +7162 -0
- package/src/posture/.agentic-security/streak.json +21 -0
- package/src/posture/api-contract.js +193 -0
- package/src/posture/attack-taxonomy.js +227 -0
- package/src/posture/compliance-policy.js +218 -0
- package/src/posture/composite-risk.js +122 -0
- package/src/posture/csharp-analysis.js +330 -0
- package/src/posture/exploit-bundle.js +210 -0
- package/src/posture/federated-learning.js +172 -0
- package/src/posture/license-attributions.js +94 -0
- package/src/posture/license-graph.js +238 -0
- package/src/posture/pqc-migration-plan.js +158 -0
- package/src/posture/reachability-filter.js +33 -2
- package/src/posture/realtime-cve-monitor.js +214 -0
- package/src/posture/runtime-correlation.js +174 -0
- package/src/posture/sbom-diff.js +171 -0
- package/src/posture/sca-policy.js +235 -0
- package/src/posture/sca-upgrade.js +259 -0
- package/src/posture/threat-model-auto.js +268 -0
- package/src/posture/triage-learning.js +170 -0
- package/src/posture/triage.js +26 -1
- package/src/sast/.agentic-security/findings.json +6154 -0
- package/src/sast/.agentic-security/last-scan.json +6154 -0
- package/src/sast/.agentic-security/last-scan.json.sig +1 -0
- package/src/sast/.agentic-security/scan-history.json +941 -0
- package/src/sast/.agentic-security/streak.json +22 -0
- package/src/sast/_secret-entropy.js +145 -0
- package/src/sast/cloud-iam.js +312 -0
- package/src/sast/cpp.js +138 -4
- package/src/sast/crypto-protocol.js +388 -0
- package/src/sast/csharp-tokenizer.js +392 -0
- package/src/sast/csharp.js +924 -138
- package/src/sast/dapp-frontend.js +200 -0
- package/src/sast/k8s-admission.js +271 -0
- package/src/sast/llm-app.js +272 -0
- package/src/sast/ml-supply-chain.js +259 -0
- package/src/sast/mobile.js +224 -0
- package/src/sast/post-quantum-crypto.js +348 -0
- package/src/sast/web3-advanced.js +375 -0
- package/src/sca/.agentic-security/findings.json +7460 -0
- package/src/sca/.agentic-security/last-scan.json +7460 -0
- package/src/sca/.agentic-security/last-scan.json.sig +1 -0
- package/src/sca/.agentic-security/scan-history.json +113 -0
- package/src/sca/.agentic-security/streak.json +21 -0
- package/src/sca/CLAUDE.md +161 -0
- package/src/sca/binary-metadata.js +37 -15
- package/src/sca/sigstore-verify.js +215 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
da76e96762f8d7ee6ac2ee8968d5822c14bee45de513ed9c1d60cf6f6694c261
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"timestamp": "2026-05-28T18:59:26.541Z",
|
|
4
|
+
"label": "scan",
|
|
5
|
+
"total": 15,
|
|
6
|
+
"critical": 0,
|
|
7
|
+
"high": 5,
|
|
8
|
+
"medium": 10,
|
|
9
|
+
"low": 0,
|
|
10
|
+
"kev": 0,
|
|
11
|
+
"ids": [
|
|
12
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
13
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
14
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
15
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
16
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
17
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
18
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
19
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
20
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
21
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
22
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
23
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
24
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
25
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
26
|
+
"toctou-fs:type-stubs.js:48"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"timestamp": "2026-05-28T19:04:00.910Z",
|
|
31
|
+
"label": "scan",
|
|
32
|
+
"total": 15,
|
|
33
|
+
"critical": 0,
|
|
34
|
+
"high": 5,
|
|
35
|
+
"medium": 10,
|
|
36
|
+
"low": 0,
|
|
37
|
+
"kev": 0,
|
|
38
|
+
"ids": [
|
|
39
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
40
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
41
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
42
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
43
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
44
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
45
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
46
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
47
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
48
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
49
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
50
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
51
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
52
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
53
|
+
"toctou-fs:type-stubs.js:48"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"timestamp": "2026-05-28T19:06:14.172Z",
|
|
58
|
+
"label": "scan",
|
|
59
|
+
"total": 15,
|
|
60
|
+
"critical": 0,
|
|
61
|
+
"high": 5,
|
|
62
|
+
"medium": 10,
|
|
63
|
+
"low": 0,
|
|
64
|
+
"kev": 0,
|
|
65
|
+
"ids": [
|
|
66
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
67
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
68
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
69
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
70
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
71
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
72
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
73
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
74
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
75
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
76
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
77
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
78
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
79
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
80
|
+
"toctou-fs:type-stubs.js:48"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"timestamp": "2026-05-28T19:06:52.695Z",
|
|
85
|
+
"label": "scan",
|
|
86
|
+
"total": 15,
|
|
87
|
+
"critical": 0,
|
|
88
|
+
"high": 5,
|
|
89
|
+
"medium": 10,
|
|
90
|
+
"low": 0,
|
|
91
|
+
"kev": 0,
|
|
92
|
+
"ids": [
|
|
93
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
94
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
95
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
96
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
97
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
98
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
99
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
100
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
101
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
102
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
103
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
104
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
105
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
106
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
107
|
+
"toctou-fs:type-stubs.js:48"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"timestamp": "2026-05-28T20:16:46.839Z",
|
|
112
|
+
"label": "scan",
|
|
113
|
+
"total": 15,
|
|
114
|
+
"critical": 0,
|
|
115
|
+
"high": 5,
|
|
116
|
+
"medium": 10,
|
|
117
|
+
"low": 0,
|
|
118
|
+
"kev": 0,
|
|
119
|
+
"ids": [
|
|
120
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
121
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
122
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
123
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
124
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
125
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
126
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
127
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
128
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
129
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
130
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
131
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
132
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
133
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
134
|
+
"toctou-fs:type-stubs.js:48"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"timestamp": "2026-05-28T21:57:00.566Z",
|
|
139
|
+
"label": "scan",
|
|
140
|
+
"total": 16,
|
|
141
|
+
"critical": 0,
|
|
142
|
+
"high": 5,
|
|
143
|
+
"medium": 11,
|
|
144
|
+
"low": 0,
|
|
145
|
+
"kev": 0,
|
|
146
|
+
"ids": [
|
|
147
|
+
"struct:cpp-preprocessor.js:94:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
148
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
149
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
150
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
151
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
152
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
153
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
154
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
155
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
156
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
157
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
158
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
159
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
160
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
161
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
162
|
+
"toctou-fs:type-stubs.js:48"
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"timestamp": "2026-05-29T06:24:38.526Z",
|
|
167
|
+
"label": "scan",
|
|
168
|
+
"total": 16,
|
|
169
|
+
"critical": 0,
|
|
170
|
+
"high": 5,
|
|
171
|
+
"medium": 11,
|
|
172
|
+
"low": 0,
|
|
173
|
+
"kev": 0,
|
|
174
|
+
"ids": [
|
|
175
|
+
"struct:cpp-preprocessor.js:94:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
176
|
+
"struct:parser-cs.js:208:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
177
|
+
"struct:parser-go.js:253:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
178
|
+
"struct:parser-kt.js:207:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
179
|
+
"struct:parser-php.js:209:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
180
|
+
"struct:parser-py-cst.js:91:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
181
|
+
"struct:parser-rb.js:201:Mass_Assignment_(req.body_Direct_to_Model)",
|
|
182
|
+
"struct:type-stubs.js:190:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
183
|
+
"struct:type-stubs.js:198:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
184
|
+
"struct:type-stubs.js:216:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
185
|
+
"struct:type-stubs.js:245:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
186
|
+
"struct:type-stubs.js:48:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
187
|
+
"struct:type-stubs.js:57:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
188
|
+
"struct:type-stubs.js:58:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
189
|
+
"struct:type-stubs.js:79:Synchronous_Blocking_I/O_(DoS_Risk_in_Server_Context)",
|
|
190
|
+
"toctou-fs:type-stubs.js:48"
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"firstScanDate": "2026-05-28T18:59:26.568Z",
|
|
3
|
+
"lastScanDate": "2026-05-29T06:24:38.574Z",
|
|
4
|
+
"totalScans": 7,
|
|
5
|
+
"daysCleanCritical": 2,
|
|
6
|
+
"lastCleanDate": "2026-05-29",
|
|
7
|
+
"lastCriticalDate": null,
|
|
8
|
+
"hasEverHadCritical": false,
|
|
9
|
+
"bestDaysCleanCritical": 2,
|
|
10
|
+
"totalFindingsAtFirstScan": 16,
|
|
11
|
+
"totalFindingsAtLastScan": 17,
|
|
12
|
+
"totalFixesInferred": 0,
|
|
13
|
+
"lastGrade": "B",
|
|
14
|
+
"bestGrade": "B",
|
|
15
|
+
"launchCheckPassedAt": null,
|
|
16
|
+
"achievements": [
|
|
17
|
+
"first-scan"
|
|
18
|
+
],
|
|
19
|
+
"previousGrade": "B"
|
|
20
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Lightweight C/C++ preprocessor — Recommendation #8 of the SCA/SAST plan.
|
|
2
|
+
//
|
|
3
|
+
// Resolves `#include` + `#define BUF[N]` patterns across header files so
|
|
4
|
+
// the strcpy-destination-size guard (cpp.js#_classifyDestBuffer) can find
|
|
5
|
+
// buffer-size declarations declared in a sibling .h.
|
|
6
|
+
//
|
|
7
|
+
// Scope (v1, intentionally narrow):
|
|
8
|
+
// - `#include "local.h"` resolved relative to the source file
|
|
9
|
+
// (`#include <…>` system headers NOT resolved — they're too noisy
|
|
10
|
+
// and don't carry security signal at this layer)
|
|
11
|
+
// - `#define IDENT VALUE` — single-line object-like macros only;
|
|
12
|
+
// function-like macros (`#define X(a,b) ...`) ignored in v1
|
|
13
|
+
// - `typedef char BufT[N];` — alias expansion when N is literal
|
|
14
|
+
//
|
|
15
|
+
// What's intentionally OUT of scope:
|
|
16
|
+
// - Multi-step macro expansion (cascade of #define A B / #define B C / use A)
|
|
17
|
+
// - Conditional compilation (#ifdef / #if / #else): we union all branches
|
|
18
|
+
// - Token-pasting (##) and stringification (#)
|
|
19
|
+
// - Compiler -D flags (would require build-system integration)
|
|
20
|
+
//
|
|
21
|
+
// The goal is not to be a complete preprocessor; it's to recover the
|
|
22
|
+
// 80% of fixed-buffer-size context that Juliet C/C++ tests scatter across
|
|
23
|
+
// `header.h` (with `#define BUFSIZE 1024`) and `source.c` (with
|
|
24
|
+
// `char buf[BUFSIZE]; strcpy(buf, src);`).
|
|
25
|
+
//
|
|
26
|
+
// Output: { defines: Map<name, value>, typedefs: Map<name, {kind,size}>,
|
|
27
|
+
// includes: string[] }
|
|
28
|
+
// where size is a literal integer when resolvable, null otherwise.
|
|
29
|
+
|
|
30
|
+
import * as fs from 'node:fs';
|
|
31
|
+
import * as path from 'node:path';
|
|
32
|
+
|
|
33
|
+
const _MAX_INCLUDE_DEPTH = 4; // refuse pathological recursion
|
|
34
|
+
const _MAX_LINES_PER_FILE = 10_000; // skip auto-generated huge headers
|
|
35
|
+
|
|
36
|
+
function _parseDefines(content) {
|
|
37
|
+
const defines = new Map();
|
|
38
|
+
for (const m of content.matchAll(/^\s*#\s*define\s+([A-Za-z_]\w*)\s+(.+?)(?:$|\/\*|\/\/)/gm)) {
|
|
39
|
+
const name = m[1];
|
|
40
|
+
let val = m[2].trim();
|
|
41
|
+
// Strip trailing line continuation backslashes.
|
|
42
|
+
val = val.replace(/\\\s*$/, '').trim();
|
|
43
|
+
// Skip function-like macros for v1.
|
|
44
|
+
if (val.startsWith('(') && /\b[A-Za-z_]\w*\s*\(/.test(val)) continue;
|
|
45
|
+
defines.set(name, val);
|
|
46
|
+
}
|
|
47
|
+
return defines;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function _parseTypedefs(content) {
|
|
51
|
+
const typedefs = new Map();
|
|
52
|
+
// typedef char BufT[1024]; / typedef unsigned char Bytes[256];
|
|
53
|
+
for (const m of content.matchAll(/typedef\s+(?:unsigned\s+|signed\s+)?(?:char|wchar_t|int8_t|uint8_t)\s+([A-Za-z_]\w*)\s*\[\s*([A-Za-z_]\w*|\d+)\s*\]\s*;/g)) {
|
|
54
|
+
const name = m[1];
|
|
55
|
+
const sizeTxt = m[2];
|
|
56
|
+
let size = null;
|
|
57
|
+
if (/^\d+$/.test(sizeTxt)) size = parseInt(sizeTxt, 10);
|
|
58
|
+
typedefs.set(name, { kind: 'char-array', size, sizeExpr: sizeTxt });
|
|
59
|
+
}
|
|
60
|
+
return typedefs;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _parseIncludes(content) {
|
|
64
|
+
const includes = [];
|
|
65
|
+
for (const m of content.matchAll(/^\s*#\s*include\s+"([^"]+)"/gm)) {
|
|
66
|
+
includes.push(m[1]);
|
|
67
|
+
}
|
|
68
|
+
return includes;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function _resolveSize(sizeExpr, defines) {
|
|
72
|
+
if (/^\d+$/.test(sizeExpr)) return parseInt(sizeExpr, 10);
|
|
73
|
+
const macro = defines.get(sizeExpr);
|
|
74
|
+
if (macro && /^\d+$/.test(macro)) return parseInt(macro, 10);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Recursively preprocess a single source file by walking its #includes.
|
|
80
|
+
* Returns the merged define table + typedef table + flat list of resolved
|
|
81
|
+
* include paths. Cycles are detected via the `visited` set.
|
|
82
|
+
*/
|
|
83
|
+
export function preprocessFile(sourcePath, opts = {}) {
|
|
84
|
+
const visited = opts.visited || new Set();
|
|
85
|
+
const depth = opts.depth || 0;
|
|
86
|
+
const result = { defines: new Map(), typedefs: new Map(), includes: [] };
|
|
87
|
+
|
|
88
|
+
const abs = path.resolve(sourcePath);
|
|
89
|
+
if (visited.has(abs)) return result;
|
|
90
|
+
visited.add(abs);
|
|
91
|
+
if (depth > _MAX_INCLUDE_DEPTH) return result;
|
|
92
|
+
|
|
93
|
+
let content;
|
|
94
|
+
try { content = fs.readFileSync(abs, 'utf8'); }
|
|
95
|
+
catch { return result; }
|
|
96
|
+
if (content.split('\n').length > _MAX_LINES_PER_FILE) return result;
|
|
97
|
+
|
|
98
|
+
// First pass on this file's own contents.
|
|
99
|
+
const localDefines = _parseDefines(content);
|
|
100
|
+
const localTypedefs = _parseTypedefs(content);
|
|
101
|
+
const includes = _parseIncludes(content);
|
|
102
|
+
|
|
103
|
+
// Recursive merge — header values are merged BEFORE local ones so that
|
|
104
|
+
// a local #undef + redefine could in principle override (we don't model
|
|
105
|
+
// #undef, but this ordering is the correct future-extension point).
|
|
106
|
+
const dir = path.dirname(abs);
|
|
107
|
+
for (const inc of includes) {
|
|
108
|
+
const child = preprocessFile(path.join(dir, inc), { visited, depth: depth + 1 });
|
|
109
|
+
for (const [k, v] of child.defines) if (!result.defines.has(k)) result.defines.set(k, v);
|
|
110
|
+
for (const [k, v] of child.typedefs) if (!result.typedefs.has(k)) result.typedefs.set(k, v);
|
|
111
|
+
result.includes.push(...child.includes, inc);
|
|
112
|
+
}
|
|
113
|
+
for (const [k, v] of localDefines) result.defines.set(k, v);
|
|
114
|
+
for (const [k, v] of localTypedefs) result.typedefs.set(k, v);
|
|
115
|
+
|
|
116
|
+
// Final pass — resolve typedef sizes that referenced a macro.
|
|
117
|
+
for (const [name, td] of result.typedefs) {
|
|
118
|
+
if (td.size === null && td.sizeExpr) {
|
|
119
|
+
const resolved = _resolveSize(td.sizeExpr, result.defines);
|
|
120
|
+
if (resolved !== null) result.typedefs.set(name, { ...td, size: resolved });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Resolve a buffer-size expression in the context of a preprocessed file.
|
|
128
|
+
* Accepts either a literal integer string or a macro name. Returns the
|
|
129
|
+
* integer size, or null if unresolvable.
|
|
130
|
+
*/
|
|
131
|
+
export function resolveSize(sizeExpr, preprocessed) {
|
|
132
|
+
return _resolveSize(sizeExpr, preprocessed.defines || new Map());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Resolve a typedef name to its size, if it's a char-array typedef.
|
|
137
|
+
*/
|
|
138
|
+
export function resolveTypedef(name, preprocessed) {
|
|
139
|
+
return preprocessed.typedefs.get(name) || null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const _internals = { _parseDefines, _parseTypedefs, _parseIncludes };
|