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,295 +1,7 @@
1
- import { METADATA_TABLE_NAMES, metadataRowOffset, } from "./ManagedMetadataLayout.js";
2
- import { MetadataRowCursor, metadataToken, readMetadataBlob, readMetadataGuid, readMetadataString, sha256Bytes, strongNameToken, } from "./ManagedMetadataHeaps.js";
3
- import { ManagedReaderFailure, managedFailure, } from "./ManagedReaderFailure.js";
4
- const rowCursor = (bytes, layout, table, row) => {
5
- const descriptor = layout.table(table);
6
- const start = metadataRowOffset(layout, table, row);
7
- if (descriptor === undefined)
8
- throw managedFailure("invalid-row", `metadata.${String(table)}`, "Metadata table is absent", start);
9
- return new MetadataRowCursor(bytes, start, start + descriptor.rowSize, `metadata.${descriptor.name}`);
10
- };
11
- const publicKeyIdentity = (bytes, kind) => ({
12
- kind: bytes.length === 0 ? "none" : kind,
13
- byte_length: bytes.length,
14
- sha256: bytes.length === 0 ? null : sha256Bytes(bytes),
15
- token: bytes.length === 0
16
- ? null
17
- : kind === "public-key"
18
- ? strongNameToken(bytes)
19
- : bytes.length === 8
20
- ? bytes.toString("hex")
21
- : null,
22
- });
23
- const readModule = (bytes, layout, maxBytes) => {
24
- const table = layout.table(0);
25
- if (table === undefined || table.rowCount === 0)
26
- return null;
27
- const cursor = rowCursor(bytes, layout, 0, 1);
28
- const generation = cursor.readUInt16();
29
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
30
- const mvid = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
31
- const encId = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
32
- const encBaseId = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
33
- return {
34
- name,
35
- generation,
36
- mvid,
37
- enc_id: encId,
38
- enc_base_id: encBaseId,
39
- token: metadataToken(0, 1),
40
- row_offset: table.offset,
41
- };
42
- };
43
- const readAssembly = (bytes, layout, maxBytes) => {
44
- const table = layout.table(32);
45
- if (table === undefined || table.rowCount === 0)
46
- return null;
47
- const cursor = rowCursor(bytes, layout, 32, 1);
48
- const hashAlgorithm = cursor.readUInt32();
49
- const version = [
50
- cursor.readUInt16(),
51
- cursor.readUInt16(),
52
- cursor.readUInt16(),
53
- cursor.readUInt16(),
54
- ].join(".");
55
- const flags = cursor.readUInt32();
56
- const key = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
57
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
58
- const culture = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
59
- return {
60
- name,
61
- version,
62
- culture: culture.length === 0 ? null : culture,
63
- flags,
64
- hash_algorithm: hashAlgorithm,
65
- public_key: publicKeyIdentity(key, (flags & 1) === 0 ? "public-key-token" : "public-key"),
66
- token: metadataToken(32, 1),
67
- row_offset: table.offset,
68
- };
69
- };
70
- const readAssemblyReference = (bytes, layout, row, maxBytes) => {
71
- const cursor = rowCursor(bytes, layout, 35, row);
72
- const version = [
73
- cursor.readUInt16(),
74
- cursor.readUInt16(),
75
- cursor.readUInt16(),
76
- cursor.readUInt16(),
77
- ].join(".");
78
- const flags = cursor.readUInt32();
79
- const keyOrToken = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
80
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
81
- const culture = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
82
- const hashValue = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
83
- return {
84
- name,
85
- version,
86
- culture: culture.length === 0 ? null : culture,
87
- flags,
88
- public_key_or_token: publicKeyIdentity(keyOrToken, (flags & 1) === 0 ? "public-key-token" : "public-key"),
89
- hash_value_sha256: hashValue.length === 0 ? null : sha256Bytes(hashValue),
90
- hash_value_length: hashValue.length,
91
- token: metadataToken(35, row),
92
- row_offset: metadataRowOffset(layout, 35, row),
93
- };
94
- };
95
- const codedToken = (raw, bits, tables) => {
96
- if (raw === 0)
97
- return null;
98
- const tag = raw & (2 ** bits - 1);
99
- const row = Math.floor(raw / 2 ** bits);
100
- const table = tables[tag];
101
- return table === undefined || row === 0 ? null : metadataToken(table, row);
102
- };
103
- const readTypeName = (bytes, layout, table, row, maxBytes) => {
104
- const descriptor = layout.table(table);
105
- if (descriptor === undefined || row < 1 || row > descriptor.rowCount)
106
- return null;
107
- const cursor = rowCursor(bytes, layout, table, row);
108
- if (table === 1)
109
- cursor.readIndex(layout.codedIndexSize("ResolutionScope"));
110
- else
111
- cursor.readUInt32();
112
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
113
- const namespace = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
114
- return namespace.length === 0 ? name : `${namespace}.${name}`;
115
- };
116
- const declaringTypeForMethod = (bytes, layout, methodRow, maxBytes) => {
117
- const types = layout.table(2);
118
- const methods = layout.table(6);
119
- if (types === undefined || methods === undefined)
120
- return null;
121
- for (let row = 1; row <= types.rowCount; row += 1) {
122
- const cursor = rowCursor(bytes, layout, 2, row);
123
- cursor.readUInt32();
124
- const nameIndex = cursor.readIndex(layout.stringIndexSize);
125
- const namespaceIndex = cursor.readIndex(layout.stringIndexSize);
126
- cursor.readIndex(layout.codedIndexSize("TypeDefOrRef"));
127
- cursor.readIndex(layout.tableIndexSize(4));
128
- const methodStart = cursor.readIndex(layout.tableIndexSize(6));
129
- const methodEnd = row === types.rowCount
130
- ? methods.rowCount + 1
131
- : methodListForType(bytes, layout, row + 1);
132
- if (methodRow < methodStart || methodRow >= methodEnd)
133
- continue;
134
- const name = readMetadataString(bytes, layout, nameIndex, maxBytes);
135
- const namespace = readMetadataString(bytes, layout, namespaceIndex, maxBytes);
136
- return namespace.length === 0 ? name : `${namespace}.${name}`;
137
- }
138
- return null;
139
- };
140
- const methodListForType = (bytes, layout, row) => {
141
- const cursor = rowCursor(bytes, layout, 2, row);
142
- cursor.readUInt32();
143
- cursor.readIndex(layout.stringIndexSize);
144
- cursor.readIndex(layout.stringIndexSize);
145
- cursor.readIndex(layout.codedIndexSize("TypeDefOrRef"));
146
- cursor.readIndex(layout.tableIndexSize(4));
147
- return cursor.readIndex(layout.tableIndexSize(6));
148
- };
149
- const attributeTypeName = (bytes, layout, rawType, maxBytes) => {
150
- const tag = rawType & 7;
151
- const row = Math.floor(rawType / 8);
152
- if (row === 0)
153
- return null;
154
- if (tag === 2)
155
- return declaringTypeForMethod(bytes, layout, row, maxBytes);
156
- if (tag !== 3)
157
- return null;
158
- const memberRefs = layout.table(10);
159
- if (memberRefs === undefined || row > memberRefs.rowCount)
160
- return null;
161
- const cursor = rowCursor(bytes, layout, 10, row);
162
- const parent = cursor.readIndex(layout.codedIndexSize("MemberRefParent"));
163
- const parentTag = parent & 7;
164
- const parentRow = Math.floor(parent / 8);
165
- if (parentTag === 0)
166
- return readTypeName(bytes, layout, 2, parentRow, maxBytes);
167
- if (parentTag === 1)
168
- return readTypeName(bytes, layout, 1, parentRow, maxBytes);
169
- if (parentTag === 3)
170
- return declaringTypeForMethod(bytes, layout, parentRow, maxBytes);
171
- return null;
172
- };
173
- const decodeCompressedLength = (blob, offset) => {
174
- const first = blob[offset];
175
- if (first === undefined)
176
- return undefined;
177
- if ((first & 0x80) === 0)
178
- return { length: first, prefix: 1 };
179
- if ((first & 0xc0) === 0x80 && blob[offset + 1] !== undefined)
180
- return {
181
- length: ((first & 0x3f) << 8) | (blob[offset + 1] ?? 0),
182
- prefix: 2,
183
- };
184
- if ((first & 0xe0) === 0xc0 &&
185
- blob[offset + 1] !== undefined &&
186
- blob[offset + 2] !== undefined &&
187
- blob[offset + 3] !== undefined)
188
- return {
189
- length: (first & 0x1f) * 0x01_00_00_00 +
190
- (blob[offset + 1] ?? 0) * 0x01_00_00 +
191
- (blob[offset + 2] ?? 0) * 0x0100 +
192
- (blob[offset + 3] ?? 0),
193
- prefix: 4,
194
- };
195
- return undefined;
196
- };
197
- const decodeFixedString = (blob) => {
198
- if (blob.length < 3 || blob.readUInt16LE(0) !== 1 || blob[2] === 0xff)
199
- return null;
200
- const length = decodeCompressedLength(blob, 2);
201
- if (length === undefined)
202
- return null;
203
- const start = 2 + length.prefix;
204
- if (start > blob.length - length.length)
205
- return null;
206
- try {
207
- return new TextDecoder("utf-8", { fatal: true }).decode(blob.subarray(start, start + length.length));
208
- }
209
- catch {
210
- return null;
211
- }
212
- };
213
- const readCustomAttribute = (bytes, layout, row, maxBytes) => {
214
- const cursor = rowCursor(bytes, layout, 12, row);
215
- const parentRaw = cursor.readIndex(layout.codedIndexSize("HasCustomAttribute"));
216
- const typeRaw = cursor.readIndex(layout.codedIndexSize("CustomAttributeType"));
217
- const value = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
218
- const parent = codedToken(parentRaw, 5, [
219
- 6, 4, 1, 2, 8, 9, 10, 0, 14, 23, 20, 17, 26, 27, 32, 35, 38, 39, 40, 42,
220
- 44, 43,
221
- ]);
222
- if (parent === null)
223
- throw managedFailure("invalid-row", "metadata.CustomAttribute", "CustomAttribute parent coded index is invalid", cursor.start);
224
- const typeName = attributeTypeName(bytes, layout, typeRaw, maxBytes);
225
- return {
226
- parent_token: parent,
227
- constructor_token: codedToken(typeRaw, 3, [undefined, undefined, 6, 10]),
228
- type_name: typeName,
229
- value_length: value.length,
230
- value_sha256: sha256Bytes(value),
231
- decoded_fixed_string: typeName === "System.Runtime.Versioning.TargetFrameworkAttribute"
232
- ? decodeFixedString(value)
233
- : null,
234
- token: metadataToken(12, row),
235
- row_offset: cursor.start,
236
- };
237
- };
238
- const readResource = (bytes, layout, row, maxBytes, directory, issues) => {
239
- const cursor = rowCursor(bytes, layout, 40, row);
240
- const declaredOffset = cursor.readUInt32();
241
- const flags = cursor.readUInt32();
242
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
243
- const implementationRaw = cursor.readIndex(layout.codedIndexSize("Implementation"));
244
- const implementationToken = codedToken(implementationRaw, 2, [38, 35, 39]);
245
- let dataLength = null;
246
- let dataSha256 = null;
247
- if (implementationRaw === 0) {
248
- if (directory === null || declaredOffset > directory.size - 4) {
249
- issues.push({
250
- code: "invalid-resource",
251
- scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
252
- offset: directory?.offset ?? null,
253
- detail: "Embedded resource offset leaves the CLI resources directory",
254
- });
255
- }
256
- else {
257
- const start = directory.offset + declaredOffset;
258
- dataLength = bytes.readUInt32LE(start);
259
- if (dataLength > directory.size - declaredOffset - 4) {
260
- issues.push({
261
- code: "invalid-resource",
262
- scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
263
- offset: start,
264
- detail: "Embedded resource length leaves the CLI resources directory",
265
- });
266
- }
267
- else if (dataLength > maxBytes) {
268
- issues.push({
269
- code: "limit-exceeded",
270
- scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
271
- offset: start + 4,
272
- detail: `Embedded resource exceeds max_heap_item_bytes ${String(maxBytes)}; digest omitted`,
273
- });
274
- }
275
- else {
276
- dataSha256 = sha256Bytes(bytes.subarray(start + 4, start + 4 + dataLength));
277
- }
278
- }
279
- }
280
- return {
281
- name,
282
- flags,
283
- visibility: (flags & 7) === 1 ? "public" : (flags & 7) === 2 ? "private" : "unknown",
284
- implementation_token: implementationToken,
285
- embedded: implementationRaw === 0,
286
- declared_offset: declaredOffset,
287
- data_length: dataLength,
288
- data_sha256: dataSha256,
289
- token: metadataToken(40, row),
290
- row_offset: cursor.start,
291
- };
292
- };
1
+ import { METADATA_TABLE_NAMES, } from "./ManagedMetadataLayout.js";
2
+ import { readAssembly, readAssemblyReference, readCustomAttribute, readModule, readResource, } from "./ManagedMetadataInventoryRows.js";
3
+ import { metadataToken } from "./ManagedMetadataHeaps.js";
4
+ import { ManagedReaderFailure } from "./ManagedReaderFailure.js";
293
5
  const safeRead = (operation, issues) => {
294
6
  try {
295
7
  return operation();
@@ -323,26 +35,31 @@ const pageRows = (descriptor, offset, limit, read) => {
323
35
  const uniqueIssues = (issues) => [
324
36
  ...new Map(issues.map((issue) => [JSON.stringify(issue), issue])).values(),
325
37
  ];
326
- /** Inventory bounded identity tables without CLR reflection or execution. */
327
- export const readManagedMetadataInventory = (bytes, layout, input, resourceDirectory) => {
328
- const issues = [];
329
- const module = safeRead(() => readModule(bytes, layout, input.maxHeapItemBytes), issues) ??
330
- null;
331
- const assembly = safeRead(() => readAssembly(bytes, layout, input.maxHeapItemBytes), issues) ?? null;
332
- const references = pageRows(layout.table(35), input.referenceOffset, input.referenceLimit, (row) => safeRead(() => readAssemblyReference(bytes, layout, row, input.maxHeapItemBytes), issues));
333
- const resources = pageRows(layout.table(40), input.resourceOffset, input.resourceLimit, (row) => safeRead(() => readResource(bytes, layout, row, input.maxHeapItemBytes, resourceDirectory, issues), issues));
334
- const attributes = pageRows(layout.table(12), input.attributeOffset, input.attributeLimit, (row) => safeRead(() => readCustomAttribute(bytes, layout, row, input.maxHeapItemBytes), issues));
335
- const referenceNames = [];
38
+ const readPagedReferences = (bytes, layout, input, issues) => pageRows(layout.table(35), input.referenceOffset, input.referenceLimit, (row) => safeRead(() => readAssemblyReference(bytes, layout, row, input.maxHeapItemBytes), issues));
39
+ const readPagedResources = ({ bytes, layout, input, resourceDirectory, issues, }) => pageRows(layout.table(40), input.resourceOffset, input.resourceLimit, (row) => safeRead(() => readResource({
40
+ bytes,
41
+ layout,
42
+ row,
43
+ maxBytes: input.maxHeapItemBytes,
44
+ directory: resourceDirectory,
45
+ issues,
46
+ }), issues));
47
+ const readPagedAttributes = (bytes, layout, input, issues) => pageRows(layout.table(12), input.attributeOffset, input.attributeLimit, (row) => safeRead(() => readCustomAttribute(bytes, layout, row, input.maxHeapItemBytes), issues));
48
+ const collectReferenceNames = (bytes, layout, maxBytes, issues) => {
49
+ const names = [];
336
50
  const referenceTable = layout.table(35);
337
51
  for (let row = 1; row <= (referenceTable?.rowCount ?? 0); row += 1) {
338
- const reference = safeRead(() => readAssemblyReference(bytes, layout, row, input.maxHeapItemBytes), issues);
52
+ const reference = safeRead(() => readAssemblyReference(bytes, layout, row, maxBytes), issues);
339
53
  if (reference !== undefined)
340
- referenceNames.push(reference.name);
54
+ names.push(reference.name);
341
55
  }
56
+ return names;
57
+ };
58
+ const collectTargetFrameworks = (bytes, layout, maxBytes, issues) => {
342
59
  const targetFrameworks = [];
343
60
  const attributeTable = layout.table(12);
344
61
  for (let row = 1; row <= (attributeTable?.rowCount ?? 0); row += 1) {
345
- const attribute = safeRead(() => readCustomAttribute(bytes, layout, row, input.maxHeapItemBytes), issues);
62
+ const attribute = safeRead(() => readCustomAttribute(bytes, layout, row, maxBytes), issues);
346
63
  if (attribute?.parent_token === metadataToken(32, 1) &&
347
64
  attribute.type_name ===
348
65
  "System.Runtime.Versioning.TargetFrameworkAttribute" &&
@@ -350,10 +67,29 @@ export const readManagedMetadataInventory = (bytes, layout, input, resourceDirec
350
67
  !targetFrameworks.includes(attribute.decoded_fixed_string))
351
68
  targetFrameworks.push(attribute.decoded_fixed_string);
352
69
  }
70
+ return targetFrameworks;
71
+ };
72
+ /** Inventory bounded identity tables without CLR reflection or execution. */
73
+ export const readManagedMetadataInventory = (bytes, layout, input, resourceDirectory) => {
74
+ const issues = [];
75
+ const module = safeRead(() => readModule(bytes, layout, input.maxHeapItemBytes), issues) ??
76
+ null;
77
+ const assembly = safeRead(() => readAssembly(bytes, layout, input.maxHeapItemBytes), issues) ?? null;
78
+ const references = readPagedReferences(bytes, layout, input, issues);
79
+ const resources = readPagedResources({
80
+ bytes,
81
+ layout,
82
+ input,
83
+ resourceDirectory,
84
+ issues,
85
+ });
86
+ const attributes = readPagedAttributes(bytes, layout, input, issues);
87
+ const referenceNames = collectReferenceNames(bytes, layout, input.maxHeapItemBytes, issues);
88
+ const targetFrameworks = collectTargetFrameworks(bytes, layout, input.maxHeapItemBytes, issues);
353
89
  return {
354
90
  module,
355
91
  assembly,
356
- targetFrameworks: targetFrameworks.sort(),
92
+ targetFrameworks: [...targetFrameworks].sort(),
357
93
  referenceNames: [...new Set(referenceNames)].sort(),
358
94
  references,
359
95
  resources,
@@ -0,0 +1,292 @@
1
+ import { metadataRowOffset, } from "./ManagedMetadataLayout.js";
2
+ import { MetadataRowCursor, metadataToken, readMetadataBlob, readMetadataGuid, readMetadataString, sha256Bytes, strongNameToken, } from "./ManagedMetadataHeaps.js";
3
+ import { managedFailure } from "./ManagedReaderFailure.js";
4
+ const rowCursor = ({ bytes, layout, table, row, }) => {
5
+ const descriptor = layout.table(table);
6
+ const start = metadataRowOffset(layout, table, row);
7
+ if (descriptor === undefined)
8
+ throw managedFailure("invalid-row", `metadata.${String(table)}`, "Metadata table is absent", start);
9
+ return new MetadataRowCursor(bytes, start, start + descriptor.rowSize, `metadata.${descriptor.name}`);
10
+ };
11
+ const publicKeyIdentity = (bytes, kind) => ({
12
+ kind: bytes.length === 0 ? "none" : kind,
13
+ byte_length: bytes.length,
14
+ sha256: bytes.length === 0 ? null : sha256Bytes(bytes),
15
+ token: bytes.length === 0
16
+ ? null
17
+ : kind === "public-key"
18
+ ? strongNameToken(bytes)
19
+ : bytes.length === 8
20
+ ? bytes.toString("hex")
21
+ : null,
22
+ });
23
+ export const readModule = (bytes, layout, maxBytes) => {
24
+ const table = layout.table(0);
25
+ if (table === undefined || table.rowCount === 0)
26
+ return null;
27
+ const cursor = rowCursor({ bytes, layout, table: 0, row: 1 });
28
+ const generation = cursor.readUInt16();
29
+ const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
30
+ const mvid = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
31
+ const encId = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
32
+ const encBaseId = readMetadataGuid(bytes, layout, cursor.readIndex(layout.guidIndexSize));
33
+ return {
34
+ name,
35
+ generation,
36
+ mvid,
37
+ enc_id: encId,
38
+ enc_base_id: encBaseId,
39
+ token: metadataToken(0, 1),
40
+ row_offset: table.offset,
41
+ };
42
+ };
43
+ export const readAssembly = (bytes, layout, maxBytes) => {
44
+ const table = layout.table(32);
45
+ if (table === undefined || table.rowCount === 0)
46
+ return null;
47
+ const cursor = rowCursor({ bytes, layout, table: 32, row: 1 });
48
+ const hashAlgorithm = cursor.readUInt32();
49
+ const version = [
50
+ cursor.readUInt16(),
51
+ cursor.readUInt16(),
52
+ cursor.readUInt16(),
53
+ cursor.readUInt16(),
54
+ ].join(".");
55
+ const flags = cursor.readUInt32();
56
+ const key = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
57
+ const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
58
+ const culture = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
59
+ return {
60
+ name,
61
+ version,
62
+ culture: culture.length === 0 ? null : culture,
63
+ flags,
64
+ hash_algorithm: hashAlgorithm,
65
+ public_key: publicKeyIdentity(key, (flags & 1) === 0 ? "public-key-token" : "public-key"),
66
+ token: metadataToken(32, 1),
67
+ row_offset: table.offset,
68
+ };
69
+ };
70
+ export const readAssemblyReference = (bytes, layout, row, maxBytes) => {
71
+ const cursor = rowCursor({ bytes, layout, table: 35, row });
72
+ const version = [
73
+ cursor.readUInt16(),
74
+ cursor.readUInt16(),
75
+ cursor.readUInt16(),
76
+ cursor.readUInt16(),
77
+ ].join(".");
78
+ const flags = cursor.readUInt32();
79
+ const keyOrToken = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
80
+ const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
81
+ const culture = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
82
+ const hashValue = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
83
+ return {
84
+ name,
85
+ version,
86
+ culture: culture.length === 0 ? null : culture,
87
+ flags,
88
+ public_key_or_token: publicKeyIdentity(keyOrToken, (flags & 1) === 0 ? "public-key-token" : "public-key"),
89
+ hash_value_sha256: hashValue.length === 0 ? null : sha256Bytes(hashValue),
90
+ hash_value_length: hashValue.length,
91
+ token: metadataToken(35, row),
92
+ row_offset: metadataRowOffset(layout, 35, row),
93
+ };
94
+ };
95
+ const codedToken = (raw, bits, tables) => {
96
+ if (raw === 0)
97
+ return null;
98
+ const tag = raw & (2 ** bits - 1);
99
+ const row = Math.floor(raw / 2 ** bits);
100
+ const table = tables[tag];
101
+ return table === undefined || row === 0 ? null : metadataToken(table, row);
102
+ };
103
+ const readTypeName = ({ bytes, layout, table, row, maxBytes, }) => {
104
+ const descriptor = layout.table(table);
105
+ if (descriptor === undefined || row < 1 || row > descriptor.rowCount)
106
+ return null;
107
+ const cursor = rowCursor({ bytes, layout, table, row });
108
+ if (table === 1)
109
+ cursor.readIndex(layout.codedIndexSize("ResolutionScope"));
110
+ else
111
+ cursor.readUInt32();
112
+ const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
113
+ const namespace = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
114
+ return namespace.length === 0 ? name : `${namespace}.${name}`;
115
+ };
116
+ const declaringTypeForMethod = (bytes, layout, methodRow, maxBytes) => {
117
+ const types = layout.table(2);
118
+ const methods = layout.table(6);
119
+ if (types === undefined || methods === undefined)
120
+ return null;
121
+ for (let row = 1; row <= types.rowCount; row += 1) {
122
+ const cursor = rowCursor({ bytes, layout, table: 2, row });
123
+ cursor.readUInt32();
124
+ const nameIndex = cursor.readIndex(layout.stringIndexSize);
125
+ const namespaceIndex = cursor.readIndex(layout.stringIndexSize);
126
+ cursor.readIndex(layout.codedIndexSize("TypeDefOrRef"));
127
+ cursor.readIndex(layout.tableIndexSize(4));
128
+ const methodStart = cursor.readIndex(layout.tableIndexSize(6));
129
+ const methodEnd = row === types.rowCount
130
+ ? methods.rowCount + 1
131
+ : methodListForType(bytes, layout, row + 1);
132
+ if (methodRow < methodStart || methodRow >= methodEnd)
133
+ continue;
134
+ const name = readMetadataString(bytes, layout, nameIndex, maxBytes);
135
+ const namespace = readMetadataString(bytes, layout, namespaceIndex, maxBytes);
136
+ return namespace.length === 0 ? name : `${namespace}.${name}`;
137
+ }
138
+ return null;
139
+ };
140
+ const methodListForType = (bytes, layout, row) => {
141
+ const cursor = rowCursor({ bytes, layout, table: 2, row });
142
+ cursor.readUInt32();
143
+ cursor.readIndex(layout.stringIndexSize);
144
+ cursor.readIndex(layout.stringIndexSize);
145
+ cursor.readIndex(layout.codedIndexSize("TypeDefOrRef"));
146
+ cursor.readIndex(layout.tableIndexSize(4));
147
+ return cursor.readIndex(layout.tableIndexSize(6));
148
+ };
149
+ const attributeTypeName = (bytes, layout, rawType, maxBytes) => {
150
+ const tag = rawType & 7;
151
+ const row = Math.floor(rawType / 8);
152
+ if (row === 0)
153
+ return null;
154
+ if (tag === 2)
155
+ return declaringTypeForMethod(bytes, layout, row, maxBytes);
156
+ if (tag !== 3)
157
+ return null;
158
+ const memberRefs = layout.table(10);
159
+ if (memberRefs === undefined || row > memberRefs.rowCount)
160
+ return null;
161
+ const cursor = rowCursor({ bytes, layout, table: 10, row });
162
+ const parent = cursor.readIndex(layout.codedIndexSize("MemberRefParent"));
163
+ const parentTag = parent & 7;
164
+ const parentRow = Math.floor(parent / 8);
165
+ if (parentTag === 0)
166
+ return readTypeName({ bytes, layout, table: 2, row: parentRow, maxBytes });
167
+ if (parentTag === 1)
168
+ return readTypeName({ bytes, layout, table: 1, row: parentRow, maxBytes });
169
+ if (parentTag === 3)
170
+ return declaringTypeForMethod(bytes, layout, parentRow, maxBytes);
171
+ return null;
172
+ };
173
+ const decodeCompressedLength = (blob, offset) => {
174
+ const first = blob[offset];
175
+ if (first === undefined)
176
+ return undefined;
177
+ if ((first & 0x80) === 0)
178
+ return { length: first, prefix: 1 };
179
+ if ((first & 0xc0) === 0x80 && blob[offset + 1] !== undefined)
180
+ return {
181
+ length: ((first & 0x3f) << 8) | (blob[offset + 1] ?? 0),
182
+ prefix: 2,
183
+ };
184
+ if ((first & 0xe0) === 0xc0 &&
185
+ blob[offset + 1] !== undefined &&
186
+ blob[offset + 2] !== undefined &&
187
+ blob[offset + 3] !== undefined)
188
+ return {
189
+ length: (first & 0x1f) * 0x01_00_00_00 +
190
+ (blob[offset + 1] ?? 0) * 0x01_00_00 +
191
+ (blob[offset + 2] ?? 0) * 0x0100 +
192
+ (blob[offset + 3] ?? 0),
193
+ prefix: 4,
194
+ };
195
+ return undefined;
196
+ };
197
+ const decodeFixedString = (blob) => {
198
+ if (blob.length < 3 || blob.readUInt16LE(0) !== 1 || blob[2] === 0xff)
199
+ return null;
200
+ const length = decodeCompressedLength(blob, 2);
201
+ if (length === undefined)
202
+ return null;
203
+ const start = 2 + length.prefix;
204
+ if (start > blob.length - length.length)
205
+ return null;
206
+ try {
207
+ return new TextDecoder("utf-8", { fatal: true }).decode(blob.subarray(start, start + length.length));
208
+ }
209
+ catch {
210
+ return null;
211
+ }
212
+ };
213
+ export const readCustomAttribute = (bytes, layout, row, maxBytes) => {
214
+ const cursor = rowCursor({ bytes, layout, table: 12, row });
215
+ const parentRaw = cursor.readIndex(layout.codedIndexSize("HasCustomAttribute"));
216
+ const typeRaw = cursor.readIndex(layout.codedIndexSize("CustomAttributeType"));
217
+ const value = readMetadataBlob(bytes, layout, cursor.readIndex(layout.blobIndexSize), maxBytes);
218
+ const parent = codedToken(parentRaw, 5, [
219
+ 6, 4, 1, 2, 8, 9, 10, 0, 14, 23, 20, 17, 26, 27, 32, 35, 38, 39, 40, 42,
220
+ 44, 43,
221
+ ]);
222
+ if (parent === null)
223
+ throw managedFailure("invalid-row", "metadata.CustomAttribute", "CustomAttribute parent coded index is invalid", cursor.start);
224
+ const typeName = attributeTypeName(bytes, layout, typeRaw, maxBytes);
225
+ return {
226
+ parent_token: parent,
227
+ constructor_token: codedToken(typeRaw, 3, [undefined, undefined, 6, 10]),
228
+ type_name: typeName,
229
+ value_length: value.length,
230
+ value_sha256: sha256Bytes(value),
231
+ decoded_fixed_string: typeName === "System.Runtime.Versioning.TargetFrameworkAttribute"
232
+ ? decodeFixedString(value)
233
+ : null,
234
+ token: metadataToken(12, row),
235
+ row_offset: cursor.start,
236
+ };
237
+ };
238
+ export const readResource = ({ bytes, layout, row, maxBytes, directory, issues, }) => {
239
+ const cursor = rowCursor({ bytes, layout, table: 40, row });
240
+ const declaredOffset = cursor.readUInt32();
241
+ const flags = cursor.readUInt32();
242
+ const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
243
+ const implementationRaw = cursor.readIndex(layout.codedIndexSize("Implementation"));
244
+ const implementationToken = codedToken(implementationRaw, 2, [38, 35, 39]);
245
+ let dataLength = null;
246
+ let dataSha256 = null;
247
+ if (implementationRaw === 0) {
248
+ if (directory === null || declaredOffset > directory.size - 4) {
249
+ issues.push({
250
+ code: "invalid-resource",
251
+ scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
252
+ offset: directory?.offset ?? null,
253
+ detail: "Embedded resource offset leaves the CLI resources directory",
254
+ });
255
+ }
256
+ else {
257
+ const start = directory.offset + declaredOffset;
258
+ dataLength = bytes.readUInt32LE(start);
259
+ if (dataLength > directory.size - declaredOffset - 4) {
260
+ issues.push({
261
+ code: "invalid-resource",
262
+ scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
263
+ offset: start,
264
+ detail: "Embedded resource length leaves the CLI resources directory",
265
+ });
266
+ }
267
+ else if (dataLength > maxBytes) {
268
+ issues.push({
269
+ code: "limit-exceeded",
270
+ scope: `metadata.ManifestResource:${metadataToken(40, row)}`,
271
+ offset: start + 4,
272
+ detail: `Embedded resource exceeds max_heap_item_bytes ${String(maxBytes)}; digest omitted`,
273
+ });
274
+ }
275
+ else {
276
+ dataSha256 = sha256Bytes(bytes.subarray(start + 4, start + 4 + dataLength));
277
+ }
278
+ }
279
+ }
280
+ return {
281
+ name,
282
+ flags,
283
+ visibility: (flags & 7) === 1 ? "public" : (flags & 7) === 2 ? "private" : "unknown",
284
+ implementation_token: implementationToken,
285
+ embedded: implementationRaw === 0,
286
+ declared_offset: declaredOffset,
287
+ data_length: dataLength,
288
+ data_sha256: dataSha256,
289
+ token: metadataToken(40, row),
290
+ row_offset: cursor.start,
291
+ };
292
+ };