rea-agents 2.0.0 → 2.2.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.
Files changed (273) hide show
  1. package/README.md +103 -38
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/AndroidApplicationService.js +17 -0
  4. package/dist/application/AppleApplicationService.js +17 -0
  5. package/dist/application/ArtifactExtraction.js +1 -1
  6. package/dist/application/ArtifactInventory/classify.js +42 -0
  7. package/dist/application/ArtifactInventory/hash.js +43 -0
  8. package/dist/application/ArtifactInventory/reader.js +41 -0
  9. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  10. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  11. package/dist/application/ArtifactInventory/types.js +10 -0
  12. package/dist/application/ArtifactInventory.js +9 -351
  13. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  14. package/dist/application/BinarySession.js +47 -270
  15. package/dist/application/BinarySessionExecution.js +28 -0
  16. package/dist/application/BinarySessionOpen.js +39 -0
  17. package/dist/application/BinarySessionRecords.js +149 -0
  18. package/dist/application/BinarySessionStatus.js +75 -0
  19. package/dist/application/CapabilityInventory.js +24 -2
  20. package/dist/application/ClientRegistrationStatus.js +11 -4
  21. package/dist/application/CrossVersionInventory.js +8 -2
  22. package/dist/application/CrossVersionInvestigation.js +1 -23
  23. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  24. package/dist/application/DirectAnalysis.js +47 -44
  25. package/dist/application/Doctor.js +156 -238
  26. package/dist/application/DoctorDiagnostics.js +180 -0
  27. package/dist/application/ElectronBoundaryAnalysis.js +23 -7
  28. package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
  29. package/dist/application/EnhancedToolPagination.js +22 -0
  30. package/dist/application/EnhancedToolTypes.js +4 -0
  31. package/dist/application/EnhancedTools.js +20 -37
  32. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  33. package/dist/application/InventoryProjectionEvidence.js +41 -0
  34. package/dist/application/InvestigationProviders.js +12 -0
  35. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  36. package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
  37. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  38. package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
  39. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  40. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  41. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  42. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  43. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  44. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  45. package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
  46. package/dist/application/JavaScriptJsonModules.js +39 -0
  47. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  48. package/dist/application/JavaScriptReplayPermission.js +16 -0
  49. package/dist/application/JavaScriptReplayService.js +182 -156
  50. package/dist/application/LinuxHopper.js +10 -0
  51. package/dist/application/MacHopper.js +22 -11
  52. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  53. package/dist/application/PermissionAuthority.js +106 -63
  54. package/dist/application/ProcessCaptureCapability.js +1 -1
  55. package/dist/application/ProcessCapturePermission.js +13 -0
  56. package/dist/application/ProcessCli.js +2 -12
  57. package/dist/application/ProcessHarness.js +1 -1
  58. package/dist/application/ProcessPairedExperiment.js +72 -0
  59. package/dist/application/ProjectPermissionStore.js +48 -9
  60. package/dist/application/RealHopperAssertions.js +76 -0
  61. package/dist/application/ReconstructionCoverageService.js +69 -0
  62. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  63. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  64. package/dist/application/Setup.js +148 -260
  65. package/dist/application/SetupClientConfiguration.js +224 -0
  66. package/dist/application/SetupClients.js +24 -2
  67. package/dist/application/SetupPlan.js +124 -12
  68. package/dist/application/SetupSkill.js +54 -36
  69. package/dist/application/SupportedClients.js +1 -0
  70. package/dist/application/Uninstall.js +12 -3
  71. package/dist/application/Upgrade.js +16 -1
  72. package/dist/application/WindowsCapabilities.js +86 -0
  73. package/dist/artifacts/AsarArtifactReader.js +11 -0
  74. package/dist/browser/BrowserProcessStartup.js +88 -0
  75. package/dist/browser/CdpCaptureDocuments.js +12 -8
  76. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  77. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  78. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  79. package/dist/browser/CdpCaptureEventState.js +1 -0
  80. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  81. package/dist/browser/CdpCaptureEvents.js +29 -496
  82. package/dist/browser/CdpObservationSession.js +51 -8
  83. package/dist/browser/CdpPageCapture.js +12 -133
  84. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  85. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  86. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  87. package/dist/browser/PngVisualDiff.js +9 -2
  88. package/dist/catalogIdentity.js +4 -0
  89. package/dist/cli/artifactCommands.js +82 -0
  90. package/dist/cli/coreAnalysisCommands.js +232 -0
  91. package/dist/cli/managedCommands.js +397 -0
  92. package/dist/cli/managedProjectGraphCommand.js +24 -0
  93. package/dist/cli/options.js +9 -0
  94. package/dist/cli/setupCommands.js +113 -0
  95. package/dist/cli/types.js +1 -0
  96. package/dist/cli/utilityCommands.js +122 -0
  97. package/dist/cli.js +10 -768
  98. package/dist/cliApplicationCommands.js +118 -4
  99. package/dist/cliBrowserAdvancedCommands.js +73 -16
  100. package/dist/cliBrowserCommands.js +39 -115
  101. package/dist/cliCommandNames.js +4 -0
  102. package/dist/cliElectronCommands.js +33 -62
  103. package/dist/cliEvidenceCommands.js +13 -2
  104. package/dist/cliInvestigationCommands.js +53 -10
  105. package/dist/cliObservationOptions.js +137 -0
  106. package/dist/cliPolicyCommands.js +80 -46
  107. package/dist/cliSetup.js +306 -0
  108. package/dist/config/environment.js +107 -0
  109. package/dist/config/parseConfig.js +228 -0
  110. package/dist/config/parsers.js +68 -0
  111. package/dist/config/permissions.js +30 -0
  112. package/dist/config/types.js +1 -0
  113. package/dist/config.js +1 -375
  114. package/dist/contracts/applicationToolContracts.js +134 -0
  115. package/dist/contracts/electronToolContracts.js +51 -3
  116. package/dist/contracts/managedToolContracts.js +8 -3
  117. package/dist/contracts/managedWorkflowToolContracts.js +3 -3
  118. package/dist/contracts/providerSelection.js +2 -0
  119. package/dist/contracts/sessionStatusContract.js +26 -0
  120. package/dist/contracts/toolContractTypes.js +12 -1
  121. package/dist/contracts/toolContracts.js +5 -12
  122. package/dist/contracts/toolEffects.js +14 -0
  123. package/dist/contracts/toolOutputSchemaGroups.js +274 -0
  124. package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
  125. package/dist/contracts/toolOutputSchemas.js +2 -550
  126. package/dist/domain/analysisErrorPresentation.js +234 -0
  127. package/dist/domain/analysisErrorProjection.js +284 -0
  128. package/dist/domain/androidApplication.js +206 -0
  129. package/dist/domain/appleApplication.js +221 -0
  130. package/dist/domain/artifactComparison.js +34 -15
  131. package/dist/domain/binaryTarget.js +87 -37
  132. package/dist/domain/boundedCartesianProjection.js +15 -0
  133. package/dist/domain/browserObservation.js +1 -285
  134. package/dist/domain/browserObservationSchemas.js +286 -0
  135. package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
  136. package/dist/domain/errors.js +4 -486
  137. package/dist/domain/functionComparison.js +4 -165
  138. package/dist/domain/functionComparisonDimensions.js +164 -0
  139. package/dist/domain/javascriptApplicationVersionItems.js +18 -6
  140. package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
  141. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  142. package/dist/domain/javascriptFeatureTraversal.js +19 -7
  143. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  145. package/dist/domain/javascriptSemanticIr.js +30 -0
  146. package/dist/domain/javascriptSemanticProjection.js +366 -0
  147. package/dist/domain/javascriptSemanticState.js +40 -0
  148. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  149. package/dist/domain/javascriptSemanticValues.js +352 -0
  150. package/dist/domain/javascriptStaticAnalysis.js +5 -221
  151. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  152. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  153. package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
  154. package/dist/domain/knownPageCoverage.js +21 -0
  155. package/dist/domain/managedApplicationGraph.js +14 -364
  156. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  157. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  158. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  159. package/dist/domain/managedArtifact.js +16 -8
  160. package/dist/domain/managedMemberComparison.js +37 -391
  161. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  162. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  163. package/dist/domain/managedNativeVerification.js +27 -389
  164. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  165. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  166. package/dist/domain/managedReconstruction.js +82 -69
  167. package/dist/domain/managedRuntimeCorrelation.js +12 -3
  168. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  169. package/dist/domain/permissionPolicy.js +2 -0
  170. package/dist/domain/processComparison.js +19 -0
  171. package/dist/domain/processPairedExperiment.js +128 -0
  172. package/dist/domain/reconstructionCoverage.js +387 -0
  173. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  174. package/dist/domain/reconstructionVerificationSchemas.js +8 -0
  175. package/dist/domain/replayMachine.js +316 -0
  176. package/dist/domain/replayMachineRuntime.js +215 -0
  177. package/dist/domain/runtimeCharacterization.js +85 -0
  178. package/dist/domain/runtimeIdentification.js +210 -0
  179. package/dist/domain/webBundleAnalyzer.js +3 -409
  180. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  181. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  182. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  183. package/dist/dotnet/ManagedArtifactInspector.js +50 -29
  184. package/dist/dotnet/ManagedMemberInspector.js +51 -785
  185. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  186. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  187. package/dist/dotnet/ManagedMemberRows.js +120 -0
  188. package/dist/dotnet/ManagedMetadataInventory.js +42 -306
  189. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  190. package/dist/dotnet/ManagedMetadataLayout.js +48 -111
  191. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  192. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  193. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  194. package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
  195. package/dist/dotnet/ManagedPeReader.js +59 -28
  196. package/dist/evaluation/CodexAgentEval.js +132 -0
  197. package/dist/generatedPackageMetadata.js +2 -2
  198. package/dist/ghidra/GhidraClient.js +76 -91
  199. package/dist/ghidra/GhidraClientStartup.js +29 -0
  200. package/dist/ghidra/GhidraClientWire.js +34 -0
  201. package/dist/ghidra/GhidraDefaults.js +1 -1
  202. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  203. package/dist/ghidra/GhidraInstallation.js +20 -15
  204. package/dist/ghidra/GhidraLauncher.js +93 -29
  205. package/dist/ghidra/GhidraProvider.js +61 -161
  206. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  207. package/dist/ghidra/GhidraSessionValues.js +2 -0
  208. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  209. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  210. package/dist/ghidra/GhidraTransport.js +71 -0
  211. package/dist/identity.js +4 -2
  212. package/dist/main/messages.js +5 -0
  213. package/dist/main/reload.js +49 -0
  214. package/dist/main/shutdown.js +25 -0
  215. package/dist/main/startup.js +14 -0
  216. package/dist/main/state.js +26 -0
  217. package/dist/main/transport.js +61 -0
  218. package/dist/main/types.js +1 -0
  219. package/dist/main.js +35 -146
  220. package/dist/process/PrivateRuntimeRoot.js +3 -2
  221. package/dist/process/ProcessOwnership.js +35 -0
  222. package/dist/process/ProviderProcess.js +2 -0
  223. package/dist/replay/JavaScriptReplayWorker.js +64 -50
  224. package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
  225. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  226. package/dist/replay/ReplayOutcome.js +95 -0
  227. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  228. package/dist/server/ProcessCaptureElicitation.js +157 -0
  229. package/dist/server/createServer.js +124 -56
  230. package/dist/server/javascriptApplicationResult.js +85 -0
  231. package/dist/server/registerApplicationTools/characterization.js +57 -0
  232. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  233. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  234. package/dist/server/registerApplicationTools/coverage.js +84 -0
  235. package/dist/server/registerApplicationTools/helpers.js +42 -0
  236. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  237. package/dist/server/registerApplicationTools/types.js +1 -0
  238. package/dist/server/registerApplicationTools.js +10 -112
  239. package/dist/server/registerBrowserTools.js +59 -83
  240. package/dist/server/registerElectronTools.js +48 -49
  241. package/dist/server/registerEnhancedTools.js +34 -42
  242. package/dist/server/registerEvidenceResources.js +56 -0
  243. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  244. package/dist/server/registerInvestigationTools/types.js +1 -0
  245. package/dist/server/registerInvestigationTools.js +83 -116
  246. package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
  247. package/dist/server/registerManagedTools.js +18 -1
  248. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  249. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  250. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  251. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  252. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  253. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  254. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  255. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  256. package/dist/server/registerManagedWorkflowTools.js +10 -274
  257. package/dist/server/registerOfficialTools.js +73 -59
  258. package/dist/server/registerSessionRecordTools.js +137 -0
  259. package/dist/server/registerSessionStatusTool.js +97 -26
  260. package/dist/server/registerSessionTools.js +60 -164
  261. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  262. package/dist/server/toolRegistrationOptions.js +101 -3
  263. package/dist/server/toolResult.js +15 -4
  264. package/package.json +11 -11
  265. package/skills/reverse-engineer-anything/SKILL.md +76 -0
  266. package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
  267. package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
  268. package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
  269. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
  270. package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
  271. package/scripts/prepare-node-pty.mjs +0 -35
  272. package/scripts/rebuild-native.mjs +0 -22
  273. package/skills/rea-analysis/SKILL.md +0 -222
@@ -1,4 +1,5 @@
1
1
  import { managedFailure } from "./ManagedReaderFailure.js";
2
+ import { computeRowSize, } from "./ManagedMetadataRowSizes.js";
2
3
  export const METADATA_TABLE_NAMES = [
3
4
  "Module",
4
5
  "TypeRef",
@@ -114,110 +115,7 @@ const codedSize = (name, rowCounts) => {
114
115
  return maximum < 2 ** (16 - descriptor.bits) ? 2 : 4;
115
116
  };
116
117
  const tableSize = (index, rows) => (rows[index] ?? 0) < 0x1_0000 ? 2 : 4;
117
- const rowSize = (table, rowCounts, heaps) => {
118
- const t = (index) => tableSize(index, rowCounts);
119
- const c = (name) => codedSize(name, rowCounts);
120
- const { string: s, guid: g, blob: b } = heaps;
121
- switch (table) {
122
- case 0:
123
- return 2 + s + g * 3;
124
- case 1:
125
- return c("ResolutionScope") + s * 2;
126
- case 2:
127
- return 4 + s * 2 + c("TypeDefOrRef") + t(4) + t(6);
128
- case 3:
129
- return t(4);
130
- case 4:
131
- return 2 + s + b;
132
- case 5:
133
- return t(6);
134
- case 6:
135
- return 8 + s + b + t(8);
136
- case 7:
137
- return t(8);
138
- case 8:
139
- return 4 + s;
140
- case 9:
141
- return t(2) + c("TypeDefOrRef");
142
- case 10:
143
- return c("MemberRefParent") + s + b;
144
- case 11:
145
- return 2 + c("HasConstant") + b;
146
- case 12:
147
- return c("HasCustomAttribute") + c("CustomAttributeType") + b;
148
- case 13:
149
- return c("HasFieldMarshal") + b;
150
- case 14:
151
- return 2 + c("HasDeclSecurity") + b;
152
- case 15:
153
- return 6 + t(2);
154
- case 16:
155
- return 4 + t(4);
156
- case 17:
157
- return b;
158
- case 18:
159
- return t(2) + t(20);
160
- case 19:
161
- return t(20);
162
- case 20:
163
- return 2 + s + c("TypeDefOrRef");
164
- case 21:
165
- return t(2) + t(23);
166
- case 22:
167
- return t(23);
168
- case 23:
169
- return 2 + s + b;
170
- case 24:
171
- return 2 + t(6) + c("HasSemantics");
172
- case 25:
173
- return t(2) + c("MethodDefOrRef") * 2;
174
- case 26:
175
- return s;
176
- case 27:
177
- return b;
178
- case 28:
179
- return 2 + c("MemberForwarded") + s + t(26);
180
- case 29:
181
- return 4 + t(4);
182
- case 30:
183
- return 8;
184
- case 31:
185
- return 4;
186
- case 32:
187
- return 16 + b + s * 2;
188
- case 33:
189
- return 4;
190
- case 34:
191
- return 12;
192
- case 35:
193
- return 12 + b * 2 + s * 2;
194
- case 36:
195
- return 4 + t(35);
196
- case 37:
197
- return 12 + t(35);
198
- case 38:
199
- return 4 + s + b;
200
- case 39:
201
- return 8 + s * 2 + c("Implementation");
202
- case 40:
203
- return 8 + s + c("Implementation");
204
- case 41:
205
- return t(2) * 2;
206
- case 42:
207
- return 4 + c("TypeOrMethodDef") + s;
208
- case 43:
209
- return c("MethodDefOrRef") + b;
210
- case 44:
211
- return t(42) + c("TypeDefOrRef");
212
- default:
213
- throw managedFailure("invalid-tables", "metadata.tables", `Metadata table ${String(table)} is unsupported`);
214
- }
215
- };
216
- /** Parse ECMA-335 stream and table layout with checked byte extents. */
217
- export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRows) => {
218
- if (size < 20 || rootOffset < 0 || rootOffset > artifact.length - size)
219
- throw managedFailure("invalid-metadata-root", "metadata.root", "CLI metadata directory leaves the artifact byte range", rootOffset);
220
- const bytes = artifact.subarray(rootOffset, rootOffset + size);
118
+ const readMetadataStreams = (bytes, rootOffset) => {
221
119
  if (bytes.readUInt32LE(0) !== 0x424a_5342)
222
120
  throw managedFailure("invalid-metadata-root", "metadata.signature", "CLI metadata signature is not BSJB", rootOffset);
223
121
  const versionLength = bytes.readUInt32LE(12);
@@ -249,10 +147,13 @@ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRo
249
147
  });
250
148
  cursor = named.next;
251
149
  }
150
+ return { streams, version };
151
+ };
152
+ const readTablesHeader = (bytes, streams) => {
252
153
  const tablesStream = streamByName(streams, ["#~", "#-"]);
253
154
  if (tablesStream === undefined)
254
155
  throw managedFailure("missing-stream", "metadata.tables", "Required metadata table stream #~ or #- is absent");
255
- const tableBytes = artifact.subarray(tablesStream.offset, tablesStream.offset + tablesStream.size);
156
+ const tableBytes = bytes.subarray(tablesStream.offset, tablesStream.offset + tablesStream.size);
256
157
  requireRange(tableBytes, 0, 24, "metadata.tables-header");
257
158
  const heapSizes = tableBytes[6] ?? 0;
258
159
  const heaps = {
@@ -263,6 +164,9 @@ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRo
263
164
  const valid = tableBytes.readBigUInt64LE(8);
264
165
  if ((valid & ~SUPPORTED_TABLE_MASK) !== 0n)
265
166
  throw managedFailure("invalid-tables", "metadata.valid-mask", "Metadata valid mask names unsupported tables outside the admitted ECMA-335 range", tablesStream.offset + 8);
167
+ return { tableBytes, tablesOffset: tablesStream.offset, heaps, valid };
168
+ };
169
+ const readRowCounts = (tableBytes, valid, maxTableRows, tablesOffset) => {
266
170
  const rowCounts = Array(METADATA_TABLE_NAMES.length).fill(0);
267
171
  let tableCursor = 24;
268
172
  for (let index = 0; index < METADATA_TABLE_NAMES.length; index += 1) {
@@ -271,30 +175,64 @@ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRo
271
175
  requireRange(tableBytes, tableCursor, 4, "metadata.table-row-count");
272
176
  const count = tableBytes.readUInt32LE(tableCursor);
273
177
  if (count > maxTableRows)
274
- throw managedFailure("limit-exceeded", `metadata.${METADATA_TABLE_NAMES[index] ?? String(index)}`, `Metadata table row count ${String(count)} exceeds max_table_rows ${String(maxTableRows)}`, tablesStream.offset + tableCursor);
178
+ throw managedFailure("limit-exceeded", `metadata.${METADATA_TABLE_NAMES[index] ?? String(index)}`, `Metadata table row count ${String(count)} exceeds max_table_rows ${String(maxTableRows)}`, tablesOffset + tableCursor);
275
179
  rowCounts[index] = count;
276
180
  tableCursor += 4;
277
181
  }
182
+ return rowCounts;
183
+ };
184
+ const buildRowSizeContext = (rowCounts, heaps) => ({
185
+ tableSize: (index) => tableSize(index, rowCounts),
186
+ codedSize: (name) => codedSize(name, rowCounts),
187
+ stringSize: heaps.string,
188
+ guidSize: heaps.guid,
189
+ blobSize: heaps.blob,
190
+ });
191
+ const buildMetadataTables = ({ tableBytes, rowCounts, heaps, valid, tablesOffset, }) => {
278
192
  const tables = new Map();
193
+ const context = buildRowSizeContext(rowCounts, heaps);
194
+ let tableCursor = 24;
195
+ for (let index = 0; index < METADATA_TABLE_NAMES.length; index += 1) {
196
+ if ((valid & (1n << BigInt(index))) === 0n)
197
+ continue;
198
+ tableCursor += 4;
199
+ }
279
200
  for (let index = 0; index < METADATA_TABLE_NAMES.length; index += 1) {
280
201
  const count = rowCounts[index] ?? 0;
281
202
  if ((valid & (1n << BigInt(index))) === 0n)
282
203
  continue;
283
- const sizeOfRow = rowSize(index, rowCounts, heaps);
204
+ const sizeOfRow = computeRowSize(index, context);
284
205
  const byteLength = count * sizeOfRow;
285
206
  if (!Number.isSafeInteger(byteLength))
286
- throw managedFailure("invalid-tables", "metadata.tables", "Metadata table byte size overflowed", tablesStream.offset + tableCursor);
207
+ throw managedFailure("invalid-tables", "metadata.tables", "Metadata table byte size overflowed", tablesOffset + tableCursor);
287
208
  requireRange(tableBytes, tableCursor, byteLength, "metadata.table-data");
288
209
  tables.set(index, {
289
210
  index,
290
211
  name: METADATA_TABLE_NAMES[index] ?? `Table${String(index)}`,
291
212
  rowCount: count,
292
213
  rowSize: sizeOfRow,
293
- offset: tablesStream.offset + tableCursor,
214
+ offset: tablesOffset + tableCursor,
294
215
  });
295
216
  tableCursor += byteLength;
296
217
  }
297
- const layout = {
218
+ return tables;
219
+ };
220
+ /** Parse ECMA-335 stream and table layout with checked byte extents. */
221
+ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRows) => {
222
+ if (size < 20 || rootOffset < 0 || rootOffset > artifact.length - size)
223
+ throw managedFailure("invalid-metadata-root", "metadata.root", "CLI metadata directory leaves the artifact byte range", rootOffset);
224
+ const bytes = artifact.subarray(rootOffset, rootOffset + size);
225
+ const { streams, version } = readMetadataStreams(bytes, rootOffset);
226
+ const { tableBytes, tablesOffset, heaps, valid } = readTablesHeader(artifact, streams);
227
+ const rowCounts = readRowCounts(tableBytes, valid, maxTableRows, tablesOffset);
228
+ const tables = buildMetadataTables({
229
+ tableBytes,
230
+ rowCounts,
231
+ heaps,
232
+ valid,
233
+ tablesOffset,
234
+ });
235
+ return {
298
236
  rootOffset,
299
237
  size,
300
238
  version,
@@ -311,7 +249,6 @@ export const readManagedMetadataLayout = (artifact, rootOffset, size, maxTableRo
311
249
  tableIndexSize: (index) => tableSize(index, rowCounts),
312
250
  codedIndexSize: (name) => codedSize(name, rowCounts),
313
251
  };
314
- return layout;
315
252
  };
316
253
  /** Resolve a one-based metadata row to its exact file offset. */
317
254
  export const metadataRowOffset = (layout, table, row) => {
@@ -0,0 +1,54 @@
1
+ import { managedFailure } from "./ManagedReaderFailure.js";
2
+ const ROW_SIZE_FACTORIES = [
3
+ ({ stringSize: s, guidSize: g }) => 2 + s + g * 3,
4
+ ({ codedSize: c, stringSize: s }) => c("ResolutionScope") + s * 2,
5
+ ({ tableSize: t, codedSize: c, stringSize: s }) => 4 + s * 2 + c("TypeDefOrRef") + t(4) + t(6),
6
+ ({ tableSize: t }) => t(4),
7
+ ({ stringSize: s, blobSize: b }) => 2 + s + b,
8
+ ({ tableSize: t }) => t(6),
9
+ ({ tableSize: t, stringSize: s, blobSize: b }) => 8 + s + b + t(8),
10
+ ({ tableSize: t }) => t(8),
11
+ ({ stringSize: s }) => 4 + s,
12
+ ({ tableSize: t, codedSize: c }) => t(2) + c("TypeDefOrRef"),
13
+ ({ codedSize: c, stringSize: s, blobSize: b }) => c("MemberRefParent") + s + b,
14
+ ({ codedSize: c, blobSize: b }) => 2 + c("HasConstant") + b,
15
+ ({ codedSize: c, blobSize: b }) => c("HasCustomAttribute") + c("CustomAttributeType") + b,
16
+ ({ codedSize: c, blobSize: b }) => c("HasFieldMarshal") + b,
17
+ ({ codedSize: c, blobSize: b }) => 2 + c("HasDeclSecurity") + b,
18
+ ({ tableSize: t }) => 6 + t(2),
19
+ ({ tableSize: t }) => 4 + t(4),
20
+ ({ blobSize: b }) => b,
21
+ ({ tableSize: t }) => t(2) + t(20),
22
+ ({ tableSize: t }) => t(20),
23
+ ({ stringSize: s, codedSize: c }) => 2 + s + c("TypeDefOrRef"),
24
+ ({ tableSize: t }) => t(2) + t(23),
25
+ ({ tableSize: t }) => t(23),
26
+ ({ stringSize: s, blobSize: b }) => 2 + s + b,
27
+ ({ tableSize: t, codedSize: c }) => 2 + t(6) + c("HasSemantics"),
28
+ ({ tableSize: t, codedSize: c }) => t(2) + c("MethodDefOrRef") * 2,
29
+ ({ stringSize: s }) => s,
30
+ ({ blobSize: b }) => b,
31
+ ({ tableSize: t, codedSize: c, stringSize: s }) => 2 + c("MemberForwarded") + s + t(26),
32
+ ({ tableSize: t }) => 4 + t(4),
33
+ () => 8,
34
+ () => 4,
35
+ ({ blobSize: b, stringSize: s }) => 16 + b + s * 2,
36
+ () => 4,
37
+ () => 12,
38
+ ({ blobSize: b, stringSize: s }) => 12 + b * 2 + s * 2,
39
+ ({ tableSize: t }) => 4 + t(35),
40
+ ({ tableSize: t }) => 12 + t(35),
41
+ ({ stringSize: s, blobSize: b }) => 4 + s + b,
42
+ ({ stringSize: s, codedSize: c }) => 8 + s * 2 + c("Implementation"),
43
+ ({ stringSize: s, codedSize: c }) => 8 + s + c("Implementation"),
44
+ ({ tableSize: t }) => t(2) * 2,
45
+ ({ stringSize: s, codedSize: c }) => 4 + c("TypeOrMethodDef") + s,
46
+ ({ codedSize: c, blobSize: b }) => c("MethodDefOrRef") + b,
47
+ ({ tableSize: t, codedSize: c }) => t(42) + c("TypeDefOrRef"),
48
+ ];
49
+ export const computeRowSize = (table, context) => {
50
+ const factory = ROW_SIZE_FACTORIES[table];
51
+ if (factory === undefined)
52
+ throw managedFailure("invalid-tables", "metadata.tables", `Metadata table ${String(table)} is unsupported`);
53
+ return factory(context);
54
+ };
@@ -0,0 +1,143 @@
1
+ import { decodeInstructions, parseExceptionRegions, } from "./ManagedMemberInstructionDecoder.js";
2
+ import { sha256Bytes } from "./ManagedMetadataHeaps.js";
3
+ const readMethodBodyHeader = (bytes, offset) => {
4
+ const first = bytes.readUInt8(offset);
5
+ if ((first & 3) === 2)
6
+ return {
7
+ format: "tiny",
8
+ size: 1,
9
+ flags: 0,
10
+ maxStack: 8,
11
+ ilSize: first >> 2,
12
+ localSig: 0,
13
+ };
14
+ if ((first & 3) !== 3)
15
+ throw new RangeError("Unsupported method body header");
16
+ if (offset > bytes.length - 12)
17
+ throw new RangeError("Fat method body header leaves artifact");
18
+ const flagsAndSize = bytes.readUInt16LE(offset);
19
+ const headerDwords = flagsAndSize >>> 12;
20
+ if (headerDwords < 3)
21
+ throw new RangeError("Fat method body header is smaller than 12 bytes");
22
+ const size = headerDwords * 4;
23
+ if (offset > bytes.length - size)
24
+ throw new RangeError("Method body header leaves artifact");
25
+ return {
26
+ format: "fat",
27
+ size,
28
+ flags: flagsAndSize & 0x0fff,
29
+ maxStack: bytes.readUInt16LE(offset + 2),
30
+ ilSize: bytes.readUInt32LE(offset + 4),
31
+ localSig: bytes.readUInt32LE(offset + 8),
32
+ };
33
+ };
34
+ export const methodBody = (bytes, pe, rva, limits) => {
35
+ if (rva === 0)
36
+ return emptyMethodBody(rva, "absent", null);
37
+ try {
38
+ const offset = pe.rvaToOffset(rva, 1, "method.body");
39
+ const header = readMethodBodyHeader(bytes, offset);
40
+ if (header.ilSize > limits.maxMethodBodyBytes)
41
+ return oversizedMethodBody(header, rva, offset, limits);
42
+ const ilOffset = offset + header.size;
43
+ if (ilOffset > bytes.length - header.ilSize)
44
+ throw new RangeError("Method IL bytes leave artifact");
45
+ const il = bytes.subarray(ilOffset, ilOffset + header.ilSize);
46
+ const decoded = decodeInstructions(il, limits.maxMethodInstructions);
47
+ const opcodeCounts = {};
48
+ for (const instruction of decoded.parsed)
49
+ opcodeCounts[instruction.opcode] =
50
+ (opcodeCounts[instruction.opcode] ?? 0) + 1;
51
+ const anchors = decoded.parsed
52
+ .map((instruction, index) => ({ instruction, index }))
53
+ .filter(({ instruction }) => instruction.operandKind !== "none")
54
+ .slice(0, limits.instructionAnchorLimit)
55
+ .map(({ instruction }) => ({
56
+ il_offset: instruction.offset,
57
+ opcode: instruction.opcode,
58
+ operand_kind: instruction.operandKind,
59
+ operand: instruction.operand,
60
+ }));
61
+ const normalized = Buffer.from(JSON.stringify(decoded.parsed.map(({ opcode, operandKind, operand }) => [
62
+ opcode,
63
+ operandKind,
64
+ operand,
65
+ ])), "utf8");
66
+ const methodEnd = ilOffset + header.ilSize;
67
+ const sectionOffset = (methodEnd + 3) & ~3;
68
+ const status = decoded.issue !== null
69
+ ? "malformed"
70
+ : decoded.truncated > 0
71
+ ? "partial"
72
+ : "present";
73
+ return {
74
+ status,
75
+ header_format: header.format,
76
+ rva,
77
+ file_offset: offset,
78
+ max_stack: header.maxStack,
79
+ init_locals: (header.flags & 0x10) !== 0,
80
+ local_var_sig_token: header.localSig === 0
81
+ ? null
82
+ : `0x${header.localSig.toString(16).padStart(8, "0")}`,
83
+ il_size: header.ilSize,
84
+ il_sha256: sha256Bytes(il),
85
+ normalized_il_sha256: status === "present" ? sha256Bytes(normalized) : null,
86
+ instruction_count: decoded.count,
87
+ decoded_instruction_count: decoded.parsed.length,
88
+ truncated_instructions: decoded.truncated,
89
+ opcode_counts: opcodeCounts,
90
+ anchors,
91
+ exception_regions: header.format === "fat" && (header.flags & 8) !== 0
92
+ ? parseExceptionRegions(bytes, sectionOffset, bytes.length)
93
+ : [],
94
+ issue: decoded.issue ??
95
+ (decoded.truncated > 0
96
+ ? `Instruction decode reached max_method_instructions ${String(limits.maxMethodInstructions)} before the end of the method body`
97
+ : null),
98
+ };
99
+ }
100
+ catch (cause) {
101
+ return emptyMethodBody(rva, "malformed", cause instanceof Error ? cause.message : "Method body parse failed");
102
+ }
103
+ };
104
+ const emptyMethodBody = (rva, status, issue) => ({
105
+ status,
106
+ header_format: status === "absent" ? "none" : "unknown",
107
+ rva,
108
+ file_offset: null,
109
+ max_stack: null,
110
+ init_locals: null,
111
+ local_var_sig_token: null,
112
+ il_size: 0,
113
+ il_sha256: null,
114
+ normalized_il_sha256: null,
115
+ instruction_count: 0,
116
+ decoded_instruction_count: 0,
117
+ truncated_instructions: 0,
118
+ opcode_counts: {},
119
+ anchors: [],
120
+ exception_regions: [],
121
+ issue,
122
+ });
123
+ const oversizedMethodBody = (header, rva, offset, limits) => ({
124
+ status: "too-large",
125
+ header_format: header.format,
126
+ rva,
127
+ file_offset: offset,
128
+ max_stack: header.maxStack,
129
+ init_locals: (header.flags & 0x10) !== 0,
130
+ local_var_sig_token: header.localSig === 0
131
+ ? null
132
+ : `0x${header.localSig.toString(16).padStart(8, "0")}`,
133
+ il_size: header.ilSize,
134
+ il_sha256: null,
135
+ normalized_il_sha256: null,
136
+ instruction_count: 0,
137
+ decoded_instruction_count: 0,
138
+ truncated_instructions: 0,
139
+ opcode_counts: {},
140
+ anchors: [],
141
+ exception_regions: [],
142
+ issue: `Method body exceeds max_method_body_bytes ${String(limits.maxMethodBodyBytes)}`,
143
+ });