@clear-capabilities/agentic-security-scanner 0.79.0 → 0.84.1

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.
Files changed (122) hide show
  1. package/dist/178.index.js +1 -1
  2. package/dist/333.index.js +283 -0
  3. package/dist/384.index.js +1 -1
  4. package/dist/637.index.js +1 -1
  5. package/dist/838.index.js +1 -1
  6. package/dist/839.index.js +170 -0
  7. package/dist/985.index.js +140 -1
  8. package/dist/agentic-security.mjs +10 -10
  9. package/dist/agentic-security.mjs.sha256 +1 -1
  10. package/package.json +7 -5
  11. package/src/.agentic-security/findings.json +117732 -0
  12. package/src/.agentic-security/last-scan.json +117732 -0
  13. package/src/.agentic-security/last-scan.json.sig +1 -0
  14. package/src/.agentic-security/scan-history.json +12946 -0
  15. package/src/.agentic-security/streak.json +21 -0
  16. package/src/dataflow/.agentic-security/findings.json +6086 -0
  17. package/src/dataflow/.agentic-security/last-scan.json +6086 -0
  18. package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
  19. package/src/dataflow/.agentic-security/scan-history.json +250 -0
  20. package/src/dataflow/.agentic-security/streak.json +21 -0
  21. package/src/dataflow/cross-service-taint.js +201 -0
  22. package/src/dataflow/formal-verify.js +204 -0
  23. package/src/dataflow/ifds-precise.js +222 -0
  24. package/src/dataflow/k2-summary-cache.js +153 -0
  25. package/src/dataflow/lib-taint-summaries.js +198 -0
  26. package/src/dataflow/privacy-taint.js +205 -0
  27. package/src/dataflow/smt-feasibility.js +189 -0
  28. package/src/engine.js +825 -127
  29. package/src/ir/.agentic-security/findings.json +4011 -0
  30. package/src/ir/.agentic-security/last-scan.json +4011 -0
  31. package/src/ir/.agentic-security/last-scan.json.sig +1 -0
  32. package/src/ir/.agentic-security/scan-history.json +193 -0
  33. package/src/ir/.agentic-security/streak.json +20 -0
  34. package/src/ir/cpp-preprocessor.js +142 -0
  35. package/src/ir/csharp-ir.js +604 -0
  36. package/src/ir/universal-ir.js +403 -0
  37. package/src/mcp/.agentic-security/findings.json +8632 -0
  38. package/src/mcp/.agentic-security/last-scan.json +8632 -0
  39. package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
  40. package/src/mcp/.agentic-security/scan-history.json +331 -0
  41. package/src/mcp/.agentic-security/streak.json +20 -0
  42. package/src/mcp/tools.js +140 -1
  43. package/src/posture/.agentic-security/findings.json +77181 -0
  44. package/src/posture/.agentic-security/last-scan.json +77181 -0
  45. package/src/posture/.agentic-security/last-scan.json.sig +1 -0
  46. package/src/posture/.agentic-security/scan-history.json +8904 -0
  47. package/src/posture/.agentic-security/streak.json +21 -0
  48. package/src/posture/api-contract.js +193 -0
  49. package/src/posture/attack-taxonomy.js +227 -0
  50. package/src/posture/auditor-walkthrough.js +252 -0
  51. package/src/posture/claude-authorship.js +197 -0
  52. package/src/posture/compliance-frameworks/.agentic-security/findings.json +80 -0
  53. package/src/posture/compliance-frameworks/.agentic-security/last-scan.json +80 -0
  54. package/src/posture/compliance-frameworks/.agentic-security/last-scan.json.sig +1 -0
  55. package/src/posture/compliance-frameworks/.agentic-security/scan-history.json +90 -0
  56. package/src/posture/compliance-frameworks/.agentic-security/streak.json +22 -0
  57. package/src/posture/compliance-frameworks/ccpa.json +32 -0
  58. package/src/posture/compliance-frameworks/eu-ai-act.json +51 -0
  59. package/src/posture/compliance-frameworks/gdpr.json +45 -0
  60. package/src/posture/compliance-frameworks/hipaa-security-rule.json +56 -0
  61. package/src/posture/compliance-frameworks/nist-ai-600-1.json +51 -0
  62. package/src/posture/compliance-frameworks/nist-csf-2.json +73 -0
  63. package/src/posture/compliance-frameworks/owasp-asvs-5.json +79 -0
  64. package/src/posture/compliance-frameworks/owasp-llm-top-10.json +69 -0
  65. package/src/posture/compliance-policy.js +218 -0
  66. package/src/posture/composite-risk.js +122 -0
  67. package/src/posture/cross-repo-memory.js +180 -0
  68. package/src/posture/csharp-analysis.js +330 -0
  69. package/src/posture/dep-add-guard.js +197 -0
  70. package/src/posture/exploit-bundle.js +210 -0
  71. package/src/posture/federated-learning.js +172 -0
  72. package/src/posture/findings-memory.js +152 -0
  73. package/src/posture/fix-style-mirror.js +118 -0
  74. package/src/posture/git-history.js +141 -0
  75. package/src/posture/intent-context.js +175 -0
  76. package/src/posture/license-attributions.js +94 -0
  77. package/src/posture/license-graph.js +238 -0
  78. package/src/posture/model-rescan.js +76 -0
  79. package/src/posture/pattern-propagation.js +39 -0
  80. package/src/posture/pqc-migration-plan.js +158 -0
  81. package/src/posture/pr-augment.js +234 -0
  82. package/src/posture/reachability-filter.js +33 -2
  83. package/src/posture/realtime-cve-monitor.js +214 -0
  84. package/src/posture/risk-dollars.js +158 -0
  85. package/src/posture/runtime-correlation.js +174 -0
  86. package/src/posture/sbom-diff.js +171 -0
  87. package/src/posture/sca-policy.js +235 -0
  88. package/src/posture/sca-upgrade.js +259 -0
  89. package/src/posture/threat-model-auto.js +268 -0
  90. package/src/posture/threat-model-grounding.js +169 -0
  91. package/src/posture/time-to-fix.js +129 -0
  92. package/src/posture/triage-learning.js +170 -0
  93. package/src/posture/triage-memory.js +151 -0
  94. package/src/posture/triage.js +40 -1
  95. package/src/posture/watch-mode.js +171 -0
  96. package/src/posture/workflow-installer.js +231 -0
  97. package/src/sast/.agentic-security/findings.json +6154 -0
  98. package/src/sast/.agentic-security/last-scan.json +6154 -0
  99. package/src/sast/.agentic-security/last-scan.json.sig +1 -0
  100. package/src/sast/.agentic-security/scan-history.json +941 -0
  101. package/src/sast/.agentic-security/streak.json +22 -0
  102. package/src/sast/_secret-entropy.js +145 -0
  103. package/src/sast/cloud-iam.js +312 -0
  104. package/src/sast/cpp.js +138 -4
  105. package/src/sast/crypto-protocol.js +388 -0
  106. package/src/sast/csharp-tokenizer.js +392 -0
  107. package/src/sast/csharp.js +924 -138
  108. package/src/sast/dapp-frontend.js +200 -0
  109. package/src/sast/k8s-admission.js +271 -0
  110. package/src/sast/llm-app.js +272 -0
  111. package/src/sast/ml-supply-chain.js +259 -0
  112. package/src/sast/mobile.js +224 -0
  113. package/src/sast/post-quantum-crypto.js +348 -0
  114. package/src/sast/web3-advanced.js +375 -0
  115. package/src/sca/.agentic-security/findings.json +7460 -0
  116. package/src/sca/.agentic-security/last-scan.json +7460 -0
  117. package/src/sca/.agentic-security/last-scan.json.sig +1 -0
  118. package/src/sca/.agentic-security/scan-history.json +113 -0
  119. package/src/sca/.agentic-security/streak.json +21 -0
  120. package/src/sca/CLAUDE.md +161 -0
  121. package/src/sca/binary-metadata.js +37 -15
  122. 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 };