rea-agents 6.0.0 → 6.1.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 (343) hide show
  1. package/README.md +23 -17
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +173 -47
  4. package/bridge/hopper_bridge.py +310 -128
  5. package/bridge/mitmproxy/capture.py +0 -2
  6. package/bridge/native/rea_lldb_tracer.py +630 -94
  7. package/bridge/process/ProcessRunTokenReader.swift +39 -5
  8. package/bridge/pwntools/recorded_crash_impl.py +4 -0
  9. package/dist/android/JadxConfiguration.js +196 -33
  10. package/dist/android/JadxMcpTransport.js +4 -0
  11. package/dist/android/JadxProtocol.js +6 -0
  12. package/dist/android/JadxProvider.js +19 -2
  13. package/dist/android/JadxSession.js +23 -4
  14. package/dist/application/AnalysisContextQueries.js +8 -35
  15. package/dist/application/AnalysisDocument.js +32 -0
  16. package/dist/application/AppBundleExecutable.js +67 -21
  17. package/dist/application/CallPathTracing.js +19 -3
  18. package/dist/application/CapabilityInventory.js +6 -3
  19. package/dist/application/ClientConfigurationDocument.js +871 -6
  20. package/dist/application/ClientRegistrationIdentity.js +26 -5
  21. package/dist/application/ClientRegistrationStatus.js +29 -14
  22. package/dist/application/DirectAnalysis.js +27 -37
  23. package/dist/application/Doctor.js +4 -2
  24. package/dist/application/DoctorScope.js +25 -13
  25. package/dist/application/EnhancedLiteralTracing.js +22 -25
  26. package/dist/application/EnhancedTools.js +13 -11
  27. package/dist/application/EvidenceBundleFiles.js +23 -11
  28. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  29. package/dist/application/InventoryProjectionEvidence.js +4 -3
  30. package/dist/application/InvestigationProviders.js +3 -2
  31. package/dist/application/JsonFiles.js +50 -28
  32. package/dist/application/ProcedureAddressResolution.js +11 -0
  33. package/dist/application/ReconstructionCoverageService.js +7 -4
  34. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  35. package/dist/application/Setup.js +13 -1
  36. package/dist/application/SetupClientConfiguration.js +10 -15
  37. package/dist/application/SetupHost.js +5 -2
  38. package/dist/application/SetupPlan.js +5 -3
  39. package/dist/application/SupportedClients.js +34 -1
  40. package/dist/application/Uninstall.js +4 -3
  41. package/dist/application/Update.js +18 -3
  42. package/dist/application/UpdateRuntime.js +46 -25
  43. package/dist/application/WebModuleTraceService.js +4 -2
  44. package/dist/application/WebNetworkCaptureService.js +4 -2
  45. package/dist/application/WebRuntimeService.js +5 -3
  46. package/dist/application/WebScriptExportService.js +2 -2
  47. package/dist/application/WebSourceLocationService.js +4 -2
  48. package/dist/application/WorkflowEvidence.js +82 -0
  49. package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
  50. package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
  51. package/dist/application/binary/AnalysisSnapshotCache.js +3 -6
  52. package/dist/application/binary/BinarySession.js +95 -68
  53. package/dist/application/binary/BinarySessionOpen.js +3 -3
  54. package/dist/application/binary/BinarySessionRecords.js +25 -3
  55. package/dist/application/binary/BinarySessionStatus.js +17 -1
  56. package/dist/application/binary/CompositeProvider.js +13 -0
  57. package/dist/application/binary/LazyAnalysisProvider.js +3 -0
  58. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
  59. package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
  60. package/dist/application/evm/EvmInterfaceService.js +4 -2
  61. package/dist/application/investigation/EvidenceLedger.js +21 -7
  62. package/dist/application/investigation/InvestigationRecords.js +8 -0
  63. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  64. package/dist/application/javascript/JavaScriptApplicationEvidence.js +24 -3
  65. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  66. package/dist/application/javascript/JavaScriptApplicationService.js +22 -15
  67. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  68. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -4
  69. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
  70. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +6 -3
  71. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +11 -3
  72. package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
  73. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  74. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
  75. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  76. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
  77. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +23 -1
  78. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  79. package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
  80. package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
  81. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  82. package/dist/application/process/ProcessCli.js +14 -6
  83. package/dist/application/process/ProcessEvidence.js +4 -3
  84. package/dist/application/workflowInputError.js +18 -0
  85. package/dist/artifacts/ArtifactProvider.js +12 -2
  86. package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
  87. package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
  88. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
  89. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  90. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  91. package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
  92. package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
  93. package/dist/artifacts/apple/NibArchive.js +81 -14
  94. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  95. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  96. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +13 -8
  97. package/dist/artifacts/inventory/scanCanonical.js +11 -14
  98. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  99. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  100. package/dist/browser/CdpCaptureEventHandlers.js +76 -11
  101. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  102. package/dist/browser/CdpCaptureEvents.js +25 -0
  103. package/dist/browser/CdpConnection.js +30 -11
  104. package/dist/browser/CdpOptionalCommand.js +2 -3
  105. package/dist/browser/CdpPageCapture.js +23 -1
  106. package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
  107. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  108. package/dist/browser/PlaywrightElectronActiveProvider.js +123 -124
  109. package/dist/browser/WebSourceMapFetcher.js +426 -72
  110. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  111. package/dist/browser/history/CaptureFailures.js +37 -1
  112. package/dist/browser/history/CaptureRelease.js +5 -0
  113. package/dist/browser/history/HarCaptureAdapter.js +3 -3
  114. package/dist/browser/history/HarJson.js +3 -2
  115. package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
  116. package/dist/cli/analysisSelector.js +23 -0
  117. package/dist/cli/applicationCommands.js +2 -3
  118. package/dist/cli/coreBinaryCommands.js +70 -12
  119. package/dist/cli/electronCommands.js +7 -6
  120. package/dist/cli/javascriptApplicationAnalysis.js +7 -3
  121. package/dist/cli/jsonOutput.js +4 -99
  122. package/dist/cli/nativeCallCommands.js +2 -3
  123. package/dist/cli/webRuntimeCommands.js +8 -8
  124. package/dist/cli.js +2 -1
  125. package/dist/cliCommandNames.js +0 -1
  126. package/dist/cliJsonInput.js +9 -4
  127. package/dist/config/environment.js +4 -0
  128. package/dist/config/ghidraStartupTimeout.js +17 -0
  129. package/dist/config/mcpResponseBudget.js +22 -0
  130. package/dist/config/parseConfig.js +2 -1
  131. package/dist/contracts/enhancedInputs.js +5 -3
  132. package/dist/contracts/enhancedToolContracts.js +3 -3
  133. package/dist/contracts/hopperMemoryContracts.js +2 -5
  134. package/dist/contracts/javascript/electronToolContracts.js +1 -1
  135. package/dist/contracts/managed/managedToolContracts.js +2 -4
  136. package/dist/contracts/native/nativeToolContracts.js +4 -2
  137. package/dist/contracts/officialToolContracts.js +14 -15
  138. package/dist/contracts/promptContracts.js +3 -3
  139. package/dist/contracts/sessionLifecycleInputs.js +3 -7
  140. package/dist/contracts/sessionStatusContract.js +2 -4
  141. package/dist/contracts/sessionToolContracts.js +4 -6
  142. package/dist/contracts/sessionToolSchemas.js +2 -5
  143. package/dist/contracts/toolContractExamples.js +0 -1
  144. package/dist/contracts/toolContractHelpers.js +4 -1
  145. package/dist/contracts/toolEffects.js +0 -1
  146. package/dist/contracts/toolOutputSchemaGroups.js +28 -27
  147. package/dist/contracts/toolOutputSchemaPrimitives.js +18 -0
  148. package/dist/contracts/toolSchemaMetadata.js +69 -10
  149. package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
  150. package/dist/domain/analysisErrorBase.js +8 -3
  151. package/dist/domain/analysisErrorCore.js +3 -1
  152. package/dist/domain/analysisErrorPresentation.js +72 -17
  153. package/dist/domain/analysisErrorProjection.js +106 -27
  154. package/dist/domain/android/androidAnalysis.js +2 -4
  155. package/dist/domain/android/androidApplication.js +17 -9
  156. package/dist/domain/apple/appleApplication.js +41 -14
  157. package/dist/domain/apple/dyldEnvironment.js +73 -0
  158. package/dist/domain/apple/dylibResolution.js +120 -9
  159. package/dist/domain/apple/dylibResolutionFindings.js +9 -7
  160. package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
  161. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  162. package/dist/domain/apple/keyedArchive.js +9 -1
  163. package/dist/domain/apple/machoContainer.js +54 -0
  164. package/dist/domain/apple/plistNumbers.js +76 -0
  165. package/dist/domain/artifactIdentity.js +29 -0
  166. package/dist/domain/artifactInventoryEvidence.js +19 -24
  167. package/dist/domain/bridgeCandidateProjection.js +71 -0
  168. package/dist/domain/browserCompleteness.js +1 -0
  169. package/dist/domain/browserObservationError.js +24 -5
  170. package/dist/domain/browserScenarioValues.js +2 -6
  171. package/dist/domain/bundleComparison.js +3 -2
  172. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  173. package/dist/domain/canonicalOrdering.js +9 -5
  174. package/dist/domain/changedBehavior.js +6 -6
  175. package/dist/domain/comparisonSourceEvidence.js +40 -0
  176. package/dist/domain/configurationErrors.js +1 -1
  177. package/dist/domain/evidence.js +64 -9
  178. package/dist/domain/evidenceBundle.js +42 -1
  179. package/dist/domain/evidenceErrors.js +12 -1
  180. package/dist/domain/explicitSensitiveFailure.js +17 -1
  181. package/dist/domain/firmware/firmwareAnalysis.js +6 -7
  182. package/dist/domain/hopperErrors.js +23 -2
  183. package/dist/domain/hopperValues.js +51 -8
  184. package/dist/domain/immutableJson.js +114 -0
  185. package/dist/domain/inputIssueProjection.js +3 -0
  186. package/dist/domain/javascript/electronActiveObservation.js +30 -4
  187. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  188. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  189. package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
  190. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  191. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  192. package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
  193. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  194. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  195. package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
  196. package/dist/domain/javascript/javascriptSemanticGraph.js +13 -0
  197. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  198. package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
  199. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  200. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  201. package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
  202. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  203. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  204. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  205. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
  206. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  207. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
  208. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  209. package/dist/domain/jsonSerialization.js +109 -0
  210. package/dist/domain/jsonValue.js +90 -6
  211. package/dist/domain/localPath.js +6 -0
  212. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  213. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  214. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  215. package/dist/domain/managed/managedNativeVerification.js +3 -9
  216. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  217. package/dist/domain/native/nativeCallObservation.js +33 -11
  218. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  219. package/dist/domain/process/processCapture.js +8 -4
  220. package/dist/domain/process/processComparison.js +38 -4
  221. package/dist/domain/process/processScenario.js +11 -10
  222. package/dist/domain/propertyListKeys.js +1 -1
  223. package/dist/domain/propertyListXmlText.js +19 -0
  224. package/dist/domain/providerAdapterError.js +1 -1
  225. package/dist/domain/providerOperationHealth.js +54 -0
  226. package/dist/domain/reconstructionVerification.js +6 -43
  227. package/dist/domain/reconstructionVerificationSchemas.js +2 -2
  228. package/dist/domain/staticRuntimeCorrelation.js +6 -43
  229. package/dist/domain/webBundleAnalysis.js +20 -8
  230. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  231. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  232. package/dist/domain/webRuntime.js +19 -5
  233. package/dist/domain/webSourceLocation.js +1 -0
  234. package/dist/firmware/FirmwareFiles.js +1 -1
  235. package/dist/generatedPackageMetadata.js +1 -1
  236. package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
  237. package/dist/ghidra/GhidraClient.js +47 -14
  238. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  239. package/dist/ghidra/GhidraFunctionValues.js +10 -7
  240. package/dist/ghidra/GhidraInstallation.js +18 -21
  241. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  242. package/dist/ghidra/GhidraJavaLaunch.js +62 -0
  243. package/dist/ghidra/GhidraLauncher.js +33 -16
  244. package/dist/ghidra/GhidraProviderCapabilities.js +14 -2
  245. package/dist/ghidra/GhidraProviderClient.js +23 -12
  246. package/dist/ghidra/GhidraSessionError.js +11 -7
  247. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  248. package/dist/ghidra/GhidraTransport.js +20 -0
  249. package/dist/hopper/BridgeLauncher.js +31 -11
  250. package/dist/hopper/HopperAnalysisProfile.js +62 -4
  251. package/dist/hopper/HopperCleanup.js +15 -3
  252. package/dist/hopper/HopperClient.js +222 -14
  253. package/dist/hopper/HopperFileOffset.js +237 -0
  254. package/dist/hopper/HopperMachOImage.js +196 -0
  255. package/dist/hopper/HopperOperationStage.js +6 -0
  256. package/dist/hopper/HopperProvider.js +63 -9
  257. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  258. package/dist/hopper/HopperRegexSearch.js +137 -0
  259. package/dist/hopper/HopperRegexWorker.js +27 -0
  260. package/dist/hopper/HopperRequestQueue.js +68 -19
  261. package/dist/hopper/HopperTargetLease.js +3 -2
  262. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  263. package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
  264. package/dist/inspector/V8InspectorProvider.js +47 -11
  265. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  266. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
  267. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  268. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  269. package/dist/mcpDoctor.js +62 -2
  270. package/dist/native/AppleDispatchCoverage.js +47 -6
  271. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  272. package/dist/native/AppleDispatchMetadata.js +6 -3
  273. package/dist/native/AppleMachoFixups.js +48 -24
  274. package/dist/native/AppleMachoSelection.js +32 -16
  275. package/dist/native/AppleObjcCategories.js +6 -2
  276. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  277. package/dist/native/AppleObjcProperties.js +2 -1
  278. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  279. package/dist/native/AppleSwiftVtables.js +21 -15
  280. package/dist/native/CommandRunner.js +81 -84
  281. package/dist/native/LldbCallTracer.js +365 -102
  282. package/dist/native/LldbRetainedObservations.js +178 -0
  283. package/dist/native/NativeCallObservation.js +62 -3
  284. package/dist/native/NativeMacOSProvider.js +98 -17
  285. package/dist/native/SignatureTargetBinding.js +155 -0
  286. package/dist/native/parsers/lipo.js +71 -1
  287. package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
  288. package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
  289. package/dist/process/DarwinProcessRunTokenReader.js +8 -9
  290. package/dist/process/ExecFileOutput.js +20 -0
  291. package/dist/process/OwnedCommand.js +7 -2
  292. package/dist/process/ProcessOwnership.js +203 -53
  293. package/dist/process/ProcessOwnershipObservation.js +49 -4
  294. package/dist/process/ProviderProcess.js +38 -7
  295. package/dist/process/capture/ProcessCaptureError.js +2 -2
  296. package/dist/process/capture/ProcessCaptureLifecycle.js +100 -34
  297. package/dist/server/EvidenceMcpServer.js +146 -0
  298. package/dist/server/createServer.js +15 -8
  299. package/dist/server/registerAndroidTools.js +2 -4
  300. package/dist/server/registerApplicationTools/helpers.js +2 -4
  301. package/dist/server/registerArtifactComparisonTool.js +11 -7
  302. package/dist/server/registerBinaryDiagnosticsTools.js +2 -4
  303. package/dist/server/registerBrowserScenarioTool.js +2 -4
  304. package/dist/server/registerBrowserTools.js +2 -4
  305. package/dist/server/registerBundleComparisonTool.js +2 -3
  306. package/dist/server/registerCloseLifecycleTool.js +8 -18
  307. package/dist/server/registerElectronTools.js +2 -4
  308. package/dist/server/registerEnhancedTools.js +18 -59
  309. package/dist/server/registerEvidenceTools.js +2 -4
  310. package/dist/server/registerEvmTools.js +2 -4
  311. package/dist/server/registerFirmwareTools.js +2 -4
  312. package/dist/server/registerFunctionComparisonTool.js +10 -6
  313. package/dist/server/registerInvestigationTools.js +7 -7
  314. package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
  315. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
  316. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
  317. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
  318. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
  319. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
  320. package/dist/server/registerOfficialTools.js +2 -4
  321. package/dist/server/registerProcessComparisonTool.js +71 -45
  322. package/dist/server/registerRecordedCrashTools.js +2 -4
  323. package/dist/server/registerSessionRecordTools.js +5 -6
  324. package/dist/server/registerSessionStatusTool.js +17 -3
  325. package/dist/server/registerSessionTools.js +11 -3
  326. package/dist/server/registerWebModuleTool.js +2 -4
  327. package/dist/server/registerWebNetworkCaptureTool.js +2 -4
  328. package/dist/server/registerWebRuntimeTools.js +3 -7
  329. package/dist/server/registerWebScriptTool.js +2 -4
  330. package/dist/server/registerWebSourceLocationTool.js +2 -4
  331. package/dist/server/runDerivedOperation.js +15 -3
  332. package/dist/server/sessionAvailabilityPolicy.js +0 -1
  333. package/dist/server/toolRegistrationOptions.js +2 -2
  334. package/dist/server/toolResult.js +62 -10
  335. package/dist/server/toolResultEncoding.js +33 -0
  336. package/install.sh +1 -1
  337. package/native/windows/build/manifest.json +1 -1
  338. package/package.json +8 -3
  339. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  340. package/scripts/electron-active-hook.cjs +241 -37
  341. package/skills/reverse-engineer-anything/SKILL.md +11 -3
  342. package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
  343. package/dist/ghidra/GhidraDefaults.js +0 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- **English** · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)
3
+ **English** · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md)
4
4
 
5
5
  # REA: Reverse Engineer Anything
6
6
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/rea-agents?style=flat-square&color=cb3837)](https://www.npmjs.com/package/rea-agents)
12
12
  [![CI](https://img.shields.io/github/actions/workflow/status/morluto/rea/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/morluto/rea/actions/workflows/ci.yml)
13
- [![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/product-catalog.json)
13
+ [![MCP tool catalog](https://img.shields.io/badge/MCP-tool_catalog-5c4ee5?style=flat-square)](docs/mcp-contracts.md#generated-catalog)
14
14
  [![Node.js 22+](https://img.shields.io/badge/Node.js-22.19%2B-339933?style=flat-square&logo=nodedotjs&logoColor=white)](https://nodejs.org/)
15
15
  [![skills.sh](https://skills.sh/b/morluto/rea?style=flat-square)](https://skills.sh/morluto/rea/reverse-engineer-anything)
16
16
  [![MIT license](https://img.shields.io/badge/license-MIT-f4c430?style=flat-square)](LICENSE)
@@ -18,7 +18,7 @@
18
18
 
19
19
  <a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&amp;utm_medium=badge&amp;utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
20
20
 
21
- **[Website](https://morluto.github.io/rea/) · [Guides](https://morluto.github.io/rea/guides/) · [Showcases](https://morluto.github.io/rea/showcase/)**
21
+ **[Website](https://rea.tools/) · [Guides](https://rea.tools/guides/) · [Showcases](https://rea.tools/showcase/)**
22
22
 
23
23
  [Quick start](#quick-start) · [How REA works](#how-rea-works) · [What you can analyze](#what-you-can-analyze) · [Showcases](#showcases) · [FAQ](#faq) · [Documentation](#documentation)
24
24
 
@@ -54,7 +54,7 @@ REA connects your agent to tools for inspecting native binaries, JavaScript and
54
54
 
55
55
  Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper or Ghidra installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs neither engine.
56
56
 
57
- > **[Visit the REA website](https://morluto.github.io/rea/)** for setup instructions, illustrated guides, and real case studies.
57
+ > **[Visit the REA website](https://rea.tools/)** for setup instructions, illustrated guides, and real case studies.
58
58
 
59
59
  ## Quick start
60
60
 
@@ -70,7 +70,7 @@ Choose your agents, review the proposed changes, and approve them. Setup adds
70
70
  REA's MCP server and matching workflow instructions, with backups of existing
71
71
  configuration. Restart your agent afterward.
72
72
 
73
- Setup supports Claude Code, Codex, Cursor, Gemini CLI and
73
+ Setup supports Claude Code, Codex, Cursor, Gemini CLI, Grok Build and
74
74
  [other agents](docs/installation.md#supported-agents). See
75
75
  [installation and setup](docs/installation.md) for provider configuration and
76
76
  manual MCP registration.
@@ -149,12 +149,12 @@ Additional tools and host support depend on the target:
149
149
 
150
150
  | Target | What REA returns | Requirements and guide |
151
151
  | ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
152
- | Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://morluto.github.io/rea/guides/native/) |
152
+ | Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) |
153
153
  | Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
154
154
  | EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier; [offline EVM guide](docs/evm-bytecode.md) |
155
155
  | Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
156
- | JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://morluto.github.io/rea/guides/javascript/) |
157
- | Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://morluto.github.io/rea/guides/browser/) |
156
+ | JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://rea.tools/guides/javascript/) |
157
+ | Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) |
158
158
  | Saved network captures | Requests, responses, exposed payloads and source locations | HAR; mitmdump on Linux for native mitmproxy captures; [capture guide](docs/web-network-captures.md) |
159
159
  | .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | Static inspection; [managed-code guide](docs/managed-code-analysis.md) |
160
160
  | Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS; [Android guide](docs/android-analysis.md) |
@@ -173,6 +173,8 @@ Native formats and host support vary by provider. See
173
173
  [IDA guide](docs/ida-provider.md), and
174
174
  [experimental Windows Ghidra support](docs/windows-ghidra-p0.md).
175
175
  Ghidra also supports [16-bit DOS analysis](docs/ghidra-dos.md).
176
+ For large binaries, raise its startup deadline with
177
+ `REA_GHIDRA_STARTUP_TIMEOUT_MS`.
176
178
  For provider selection, see the [CLI guide](docs/cli.md#choose-a-provider).
177
179
  Check [release availability](docs/installation.md#released-package-and-main)
178
180
  for features added since the latest npm release.
@@ -185,7 +187,7 @@ Follow a sound call into its position-to-pan helper, inspect the instructions,
185
187
  and turn incomplete pseudocode into C. The reconstruction passes 3,205
186
188
  original-x86 cases and reproduces all 63 compiled function bytes.
187
189
 
188
- [Read the case study](https://morluto.github.io/rea/showcase/dx-ball/) ·
190
+ [Read the case study](https://rea.tools/showcase/dx-ball/) ·
189
191
  [Reconstruction repository](https://github.com/N0zoM1z0/dx-ball)
190
192
 
191
193
  ### Notion: trace the Electron clipboard bridge
@@ -193,7 +195,7 @@ original-x86 cases and reproduces all 63 compiled function bytes.
193
195
  Find the renderer's clipboard API, follow it through preload and IPC into the
194
196
  main process, and inspect the rich clipboard format.
195
197
 
196
- [Read the case study](https://morluto.github.io/rea/showcase/notion/)
198
+ [Read the case study](https://rea.tools/showcase/notion/)
197
199
 
198
200
  ### TH04: recover a DOS bullet-ring calculation
199
201
 
@@ -201,7 +203,7 @@ Inspect the original PC-98 game's 16-bit instructions, recover the fixed and
201
203
  aimed angle calculations, and compare the reconstructed C++ with the
202
204
  historical compiler output.
203
205
 
204
- [Read the case study](https://morluto.github.io/rea/showcase/th04/) ·
206
+ [Read the case study](https://rea.tools/showcase/th04/) ·
205
207
  [Reconstruction repository](https://github.com/N0zoM1z0/th04)
206
208
 
207
209
  If you've used REA on something interesting, we'd love to see it. Share your
@@ -289,14 +291,14 @@ with your REA version, target type, steps to reproduce and error output.
289
291
 
290
292
  ## Documentation
291
293
 
292
- Start with the website's [worked guides](https://morluto.github.io/rea/guides/).
294
+ Start with the website's [worked guides](https://rea.tools/guides/).
293
295
  For exact options, prerequisites and result contracts:
294
296
 
295
297
  - [Installation and setup](docs/installation.md): agent registration, provider configuration, updates and uninstall.
296
298
  - [Readiness and troubleshooting](docs/installation.md#check-readiness-for-your-task): diagnose one agent or analysis engine.
297
299
  - [CLI and Evidence](docs/cli.md): commands, provider selection, snapshots, import/export and exit statuses.
298
300
  - [MCP contracts](docs/mcp-contracts.md) and [agent prompts](docs/mcp-prompts.md): tool results, sessions and guided investigations.
299
- - [Tool catalog](docs/product-catalog.json): generated inventory of tools, providers and CLI commands.
301
+ - [Tool catalog](docs/mcp-contracts.md#generated-catalog): build-generated inventory of tools, providers and CLI commands.
300
302
  - [Roadmap](docs/roadmap.md): planned work and capability trackers.
301
303
 
302
304
  Report vulnerabilities through [SECURITY.md](SECURITY.md).
@@ -313,13 +315,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
313
315
 
314
316
  ## Project links
315
317
 
316
- [Website](https://morluto.github.io/rea/) · [npm](https://www.npmjs.com/package/rea-agents) · [skills.sh](https://skills.sh/morluto/rea/reverse-engineer-anything) · [Issues](https://github.com/morluto/rea/issues) · [Security](SECURITY.md)
318
+ [Website](https://rea.tools/) · [npm](https://www.npmjs.com/package/rea-agents) · [skills.sh](https://skills.sh/morluto/rea/reverse-engineer-anything) · [Issues](https://github.com/morluto/rea/issues) · [Security](SECURITY.md)
317
319
 
318
- ## License
320
+ ## Star history
319
321
 
320
- [MIT](LICENSE)
322
+ 🎉 **20,000 GitHub stars — thank you!**
321
323
 
322
- ## Star history
324
+ Thanks to everyone using REA, reporting bugs, testing builds, and contributing fixes.
323
325
 
324
326
  <a href="https://www.star-history.com/?repos=morluto%2Frea&amp;type=date">
325
327
  <picture>
@@ -332,3 +334,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
332
334
  ## Disclaimer
333
335
 
334
336
  REA provides tools for lawful reverse-engineering research, analysis, and reconstruction. You are responsible for obtaining any required authorization and complying with applicable laws. The project does not endorse illegal or unauthorized use.
337
+
338
+ ## License
339
+
340
+ [MIT](LICENSE)
@@ -25,6 +25,11 @@ class ReaJadxBridge {
25
25
  private record MethodSnapshot(String name, String shortId, Map<String, Object> summary) {}
26
26
  private record ClassSnapshot(JavaClass node, List<MethodSnapshot> methods, Map<String, Object> summary) {}
27
27
 
28
+ private static final class InputFailure extends IllegalArgumentException {
29
+ final String field;
30
+ InputFailure(String field, String message) { super(message); this.field = field; }
31
+ }
32
+
28
33
  private ReaJadxBridge(SessionHolder holder) { this.holder = holder; }
29
34
 
30
35
  private static CallToolResult text(String value, boolean failed) {
@@ -100,8 +105,9 @@ class ReaJadxBridge {
100
105
  }
101
106
  String name = string(args, "class_name");
102
107
  List<ClassSnapshot> candidates = classes.get(name);
103
- if (candidates == null) throw new IllegalArgumentException("Exact class not found: " + name);
104
- if (candidates.size() != 1) throw new IllegalArgumentException("Ambiguous metadata class identity: " + name
108
+ if (candidates == null) throw new InputFailure("class_name", "Exact class not found: " + name
109
+ + "; use search_android_classes to discover fully qualified names.");
110
+ if (candidates.size() != 1) throw new InputFailure("class_name", "Ambiguous metadata class identity: " + name
105
111
  + "; raw identities: " + candidates.stream().map(candidate -> candidate.node().getRawName()).toList());
106
112
  return candidates.get(0);
107
113
  }
@@ -109,7 +115,8 @@ class ReaJadxBridge {
109
115
  private List<MethodSnapshot> methods(ClassSnapshot cls, JsonObject args) {
110
116
  String name = string(args, "method_name");
111
117
  List<MethodSnapshot> result = cls.methods().stream().filter(method -> method.name().equals(name)).toList();
112
- if (result.isEmpty()) throw new IllegalArgumentException("Method not found: " + name);
118
+ if (result.isEmpty()) throw new InputFailure("method_name", "Method not found: " + name
119
+ + "; use inspect_android_class to discover available methods.");
113
120
  return result;
114
121
  }
115
122
 
@@ -141,7 +148,7 @@ class ReaJadxBridge {
141
148
  if (name.equals("get_method_body")) {
142
149
  List<MethodSnapshot> overloads = methods(cls, args);
143
150
  int index = integer(args, "overload_index", 0);
144
- if (index >= overloads.size()) throw new IllegalArgumentException("overload_index out of range: " + index);
151
+ if (index >= overloads.size()) throw new InputFailure("overload_index", "overload_index out of range: " + index);
145
152
  JavaMethod method = method(cls, overloads.get(index));
146
153
  JadxSession.SmartCode code = current.getMethodBodySmart(method, current.getMaxSourceBytes(), true);
147
154
  return json(Map.of("class_name", cls.summary().get("full_name"),
@@ -155,7 +162,7 @@ class ReaJadxBridge {
155
162
  if (name.equals("get_xrefs_to_class")) uses = cls.node().getUseIn();
156
163
  else {
157
164
  List<MethodSnapshot> overloads = methods(cls, args);
158
- if (overloads.size() != 1) throw new IllegalArgumentException("Method references require a unique overload");
165
+ if (overloads.size() != 1) throw new InputFailure("method_name", "Method references require a unique overload");
159
166
  target += "." + overloads.get(0).name();
160
167
  uses = method(cls, overloads.get(0)).getUseIn();
161
168
  }
@@ -211,6 +218,8 @@ class ReaJadxBridge {
211
218
  tool.getInputSchema().getRequired(), null), description, null, null, null, null, null, null);
212
219
  server.addTool(narrowed, (connection, request, continuation) -> {
213
220
  try { return bridge.handle(name, request.getArguments()); }
221
+ catch (InputFailure error) { return text(JSON.toJson(Map.of(
222
+ "kind", "invalid-input", "field", error.field, "message", error.getMessage())), true); }
214
223
  catch (IllegalArgumentException error) { return text(error.getMessage(), true); }
215
224
  });
216
225
  }
@@ -52,6 +52,8 @@ import ghidra.app.decompiler.ClangCaseToken;
52
52
  import ghidra.app.decompiler.ClangNode;
53
53
  import ghidra.framework.Application;
54
54
  import ghidra.program.model.address.Address;
55
+ import ghidra.program.model.address.AddressIterator;
56
+ import ghidra.program.model.address.AddressSet;
55
57
  import ghidra.program.model.address.AddressSpace;
56
58
  import ghidra.program.model.address.AddressRange;
57
59
  import ghidra.program.model.address.AddressRangeIterator;
@@ -723,8 +725,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
723
725
  if (!direction.equals("incoming") && !direction.equals("outgoing")) {
724
726
  throw new RequestFailure("invalid_request", "direction must be incoming or outgoing");
725
727
  }
726
- InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
727
- List<Reference> references = collectReferences(scan.instructions, direction);
728
+ List<Reference> references = collectReferences(function, direction);
728
729
  JsonArray edges = new JsonArray();
729
730
  for (Reference reference : references) {
730
731
  edges.add(referenceEdge(reference));
@@ -735,7 +736,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
735
736
  result.add("references", edges);
736
737
  result.addProperty("reference_kinds_available", true);
737
738
  JsonArray unresolvedCalls = new JsonArray();
738
- if (direction.equals("outgoing")) for (Instruction instruction : scan.instructions) {
739
+ if (direction.equals("outgoing")) for (Instruction instruction : scanInstructions(function, Integer.MAX_VALUE).instructions) {
739
740
  if (!instruction.getFlowType().isCall()) continue;
740
741
  boolean resolved = false;
741
742
  for (Reference reference : instruction.getReferencesFrom()) if (reference.getReferenceType().isCall()) resolved = true;
@@ -1007,6 +1008,11 @@ public final class ReaGhidraBridge extends HeadlessScript {
1007
1008
  Address entry = function.getEntryPoint();
1008
1009
  if (function.isExternal() || !currentProgram.getMemory().contains(entry))
1009
1010
  throw new RequestFailure("invalid_request", "Annotations require a local function entry: " + canonicalAddress(entry));
1011
+ for (String field : List.of("name", "comment", "inline_comment")) {
1012
+ if (params.has(field)) validateAnnotationText(requireText(params, field), field);
1013
+ }
1014
+ String leafName = params.has("name")
1015
+ ? annotationLeafName(function, requireString(params, "name")) : null;
1010
1016
  int transaction = currentProgram.startTransaction("REA function annotations");
1011
1017
  boolean commit = false;
1012
1018
  try {
@@ -1020,7 +1026,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
1020
1026
  }
1021
1027
  }
1022
1028
  if (params.has("name"))
1023
- function.setName(requireString(params, "name"), SourceType.USER_DEFINED);
1029
+ function.setName(leafName, SourceType.USER_DEFINED);
1024
1030
  monitor.checkCancelled();
1025
1031
  invalidateAnalysisCaches();
1026
1032
  JsonObject readback = annotationReadback(function);
@@ -1028,7 +1034,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
1028
1034
  if (!params.has(field)) continue;
1029
1035
  String requested = requireText(params, field);
1030
1036
  JsonElement measured = readback.get(field);
1031
- String expected = !field.equals("name") && requested.isEmpty() ? null : requested;
1037
+ String expected = field.equals("name") ? leafName : requested.isEmpty() ? null : requested;
1032
1038
  String observed = field.equals("name") ? function.getName() :
1033
1039
  (measured.isJsonNull() ? null : measured.getAsString());
1034
1040
  if (!java.util.Objects.equals(expected, observed))
@@ -1058,6 +1064,22 @@ public final class ReaGhidraBridge extends HeadlessScript {
1058
1064
  }
1059
1065
  }
1060
1066
 
1067
+ private String annotationLeafName(Function function, String requested) {
1068
+ // Fully qualified readback must be usable as an idempotent rename input.
1069
+ if (requested.equals(procedureName(function))) return function.getName();
1070
+ String namespace = function.getParentNamespace().isGlobal()
1071
+ ? "" : function.getParentNamespace().getName(true);
1072
+ String prefix = namespace + "::";
1073
+ if (!namespace.isEmpty() && requested.startsWith(prefix)) {
1074
+ String leaf = requested.substring(prefix.length());
1075
+ if (!leaf.isEmpty()) return leaf;
1076
+ throw new RequestFailure("invalid_function_name",
1077
+ "Function name has an empty leaf within namespace " + namespace + " at " +
1078
+ canonicalAddress(function.getEntryPoint()) + ": " + requested);
1079
+ }
1080
+ return requested;
1081
+ }
1082
+
1061
1083
  private static String requireText(JsonObject params, String field) {
1062
1084
  JsonElement value = params.get(field);
1063
1085
  if (value == null || !value.isJsonPrimitive() || !value.getAsJsonPrimitive().isString())
@@ -1065,6 +1087,21 @@ public final class ReaGhidraBridge extends HeadlessScript {
1065
1087
  return value.getAsString();
1066
1088
  }
1067
1089
 
1090
+ private static void validateAnnotationText(String text, String field) {
1091
+ for (int index = 0; index < text.length(); index++) {
1092
+ char character = text.charAt(index);
1093
+ if (character == 0)
1094
+ throw new RequestFailure("invalid_request", "Annotation " + field + " contains NUL at UTF-16 index " + index + "; Ghidra's decompiler cannot marshal NUL text");
1095
+ if (Character.isHighSurrogate(character) && index + 1 < text.length() &&
1096
+ Character.isLowSurrogate(text.charAt(index + 1))) {
1097
+ index++;
1098
+ continue;
1099
+ }
1100
+ if (Character.isSurrogate(character))
1101
+ throw new RequestFailure("invalid_request", "Annotation " + field + " contains an unpaired Unicode surrogate at UTF-16 index " + index + "; Ghidra cannot preserve it as annotation text");
1102
+ }
1103
+ }
1104
+
1068
1105
  private JsonObject analyzeFunction(JsonObject params) throws Exception {
1069
1106
  requireKeys(params, Set.of("procedure"));
1070
1107
  Function function = resolveProcedure(requireString(params, "procedure"));
@@ -1074,11 +1111,11 @@ public final class ReaGhidraBridge extends HeadlessScript {
1074
1111
  if (pseudocode == null) {
1075
1112
  pseudocode = "";
1076
1113
  }
1077
- List<Reference> incomingReferences = collectReferences(scan.instructions, "incoming")
1114
+ List<Reference> incomingReferences = collectReferences(function, "incoming")
1078
1115
  .stream()
1079
1116
  .filter(reference -> !function.getBody().contains(reference.getFromAddress()))
1080
1117
  .toList();
1081
- List<Reference> outgoingReferences = collectReferences(scan.instructions, "outgoing");
1118
+ List<Reference> outgoingReferences = collectReferences(function, "outgoing");
1082
1119
  JsonArray incoming = referenceEdges(incomingReferences);
1083
1120
  JsonArray outgoing = referenceEdges(outgoingReferences);
1084
1121
  JsonArray comments = comments(scan.instructions);
@@ -1471,6 +1508,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
1471
1508
  : regexMatcher(expression, caseSensitive);
1472
1509
  JsonArray items = new JsonArray();
1473
1510
  for (InventoryItem item : inventory) {
1511
+ monitor.checkCancelled();
1474
1512
  if (!matcher.matches(item.value)) {
1475
1513
  continue;
1476
1514
  }
@@ -1581,33 +1619,36 @@ public final class ReaGhidraBridge extends HeadlessScript {
1581
1619
  }
1582
1620
 
1583
1621
  private Function resolveProcedure(String value) throws Exception {
1584
- Address address = tryParseAddress(value);
1585
- if (address != null) {
1586
- Function function = currentProgram.getFunctionManager().getFunctionAt(address);
1587
- if (function == null && address.isMemoryAddress()) {
1588
- function = currentProgram.getFunctionManager().getFunctionContaining(address);
1589
- }
1590
- if (function == null) {
1591
- throw new RequestFailure("not_found", "No procedure exists at the requested address");
1592
- }
1593
- return function;
1594
- }
1595
- List<Function> matches = new ArrayList<>();
1596
- for (FunctionEntry entry : procedures()) {
1597
- Function function = entry.function;
1598
- Symbol symbol = function.getSymbol();
1599
- String qualified = symbol == null ? function.getName() : symbol.getName(true);
1600
- if (function.getName().equals(value) || qualified.equals(value)) {
1601
- matches.add(function);
1622
+ // Explicit address syntax wins; an unprefixed identifier is first an
1623
+ // exact symbol name, even when every character is a hexadecimal digit.
1624
+ boolean explicitAddress = isExplicitReaAddress(value);
1625
+ if (!explicitAddress) {
1626
+ List<Function> matches = new ArrayList<>();
1627
+ for (FunctionEntry entry : procedures()) {
1628
+ monitor.checkCancelled();
1629
+ Function function = entry.function;
1630
+ Symbol symbol = function.getSymbol();
1631
+ String qualified = symbol == null ? function.getName() : symbol.getName(true);
1632
+ if (function.getName().equals(value) || qualified.equals(value)) {
1633
+ matches.add(function);
1634
+ }
1602
1635
  }
1636
+ if (matches.size() > 1)
1637
+ throw new RequestFailure("ambiguous", "Ghidra procedure name is ambiguous: " + value +
1638
+ "; select an exact entry address from " + matches.stream()
1639
+ .map(function -> canonicalAddress(function.getEntryPoint())).toList());
1640
+ if (matches.size() == 1) return matches.get(0);
1603
1641
  }
1604
- if (matches.isEmpty()) {
1605
- throw new RequestFailure("not_found", "Unknown Ghidra procedure name");
1606
- }
1607
- if (matches.size() != 1) {
1608
- throw new RequestFailure("ambiguous", "Ghidra procedure name is ambiguous");
1609
- }
1610
- return matches.get(0);
1642
+ // Retain legacy bare-hex address input only when no symbol matches.
1643
+ Address address = explicitAddress ? parseReaAddress(value) : tryParseAddress(value);
1644
+ if (address == null)
1645
+ throw new RequestFailure("not_found", "Unknown Ghidra procedure name or address: " + value);
1646
+ Function function = currentProgram.getFunctionManager().getFunctionAt(address);
1647
+ if (function == null && address.isMemoryAddress())
1648
+ function = currentProgram.getFunctionManager().getFunctionContaining(address);
1649
+ if (function == null)
1650
+ throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value);
1651
+ return function;
1611
1652
  }
1612
1653
 
1613
1654
  private JsonObject nativeApiBoundary(
@@ -2530,21 +2571,32 @@ public final class ReaGhidraBridge extends HeadlessScript {
2530
2571
  }
2531
2572
 
2532
2573
  private List<Reference> collectReferences(
2533
- List<Instruction> instructions,
2574
+ Function function,
2534
2575
  String direction) throws Exception {
2576
+ // References can target instruction interiors or originate in embedded
2577
+ // data. Use actual body ownership, including an external's exact entry.
2578
+ AddressSet scope = new AddressSet(function.getBody());
2579
+ scope.add(function.getEntryPoint());
2580
+ boolean outgoing = direction.equals("outgoing");
2581
+ AddressIterator addresses = outgoing
2582
+ ? currentProgram.getReferenceManager().getReferenceSourceIterator(scope, true)
2583
+ : currentProgram.getReferenceManager().getReferenceDestinationIterator(scope, true);
2535
2584
  TreeMap<String, Reference> observed = new TreeMap<>();
2536
- for (Instruction instruction : instructions) {
2585
+ while (addresses.hasNext()) {
2537
2586
  monitor.checkCancelled();
2538
- if (direction.equals("outgoing")) {
2587
+ Address address = addresses.next();
2588
+ if (outgoing) {
2539
2589
  for (Reference reference : currentProgram.getReferenceManager()
2540
- .getReferencesFrom(instruction.getAddress())) {
2590
+ .getReferencesFrom(address)) {
2591
+ monitor.checkCancelled();
2541
2592
  addReference(observed, reference);
2542
2593
  }
2543
2594
  }
2544
2595
  else {
2545
2596
  ReferenceIterator iterator = currentProgram.getReferenceManager()
2546
- .getReferencesTo(instruction.getAddress());
2597
+ .getReferencesTo(address);
2547
2598
  while (iterator.hasNext()) {
2599
+ monitor.checkCancelled();
2548
2600
  addReference(observed, iterator.next());
2549
2601
  }
2550
2602
  }
@@ -2944,10 +2996,46 @@ public final class ReaGhidraBridge extends HeadlessScript {
2944
2996
  return parseReaAddress(requireString(params, name));
2945
2997
  }
2946
2998
 
2999
+ private static boolean isExplicitReaAddress(String value) {
3000
+ if (value.regionMatches(true, 0, "0x", 0, 2) &&
3001
+ isHexadecimal(value, 2, value.length()))
3002
+ return true;
3003
+ int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
3004
+ if (separator <= 0 || !isHexadecimal(value, separator + 3, value.length()))
3005
+ return false;
3006
+ // Classify the encoded space iteratively. A repeated regex alternation
3007
+ // can exhaust Java's stack on a long ordinary symbol name.
3008
+ for (int index = 0; index < separator; index++) {
3009
+ char item = value.charAt(index);
3010
+ if ((item >= 'A' && item <= 'Z') ||
3011
+ (item >= 'a' && item <= 'z') ||
3012
+ (item >= '0' && item <= '9') ||
3013
+ item == '.' || item == '_' || item == '~' || item == '-')
3014
+ continue;
3015
+ if (item != '%' || index + 2 >= separator ||
3016
+ !isHexadecimal(value, index + 1, index + 3))
3017
+ return false;
3018
+ index += 2;
3019
+ }
3020
+ return true;
3021
+ }
3022
+
3023
+ private static boolean isHexadecimal(String value, int start, int end) {
3024
+ if (start >= end) return false;
3025
+ for (int index = start; index < end; index++) {
3026
+ char item = value.charAt(index);
3027
+ if (!((item >= '0' && item <= '9') ||
3028
+ (item >= 'a' && item <= 'f') ||
3029
+ (item >= 'A' && item <= 'F')))
3030
+ return false;
3031
+ }
3032
+ return true;
3033
+ }
3034
+
2947
3035
  private Address parseReaAddress(String value) {
2948
3036
  Address address = tryParseAddress(value);
2949
3037
  if (address == null) {
2950
- throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address");
3038
+ throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address: " + value);
2951
3039
  }
2952
3040
  return address;
2953
3041
  }
@@ -2956,22 +3044,31 @@ public final class ReaGhidraBridge extends HeadlessScript {
2956
3044
  try {
2957
3045
  String spaceName = null;
2958
3046
  String offset = value;
2959
- int separator = value.lastIndexOf(":0x");
3047
+ int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
2960
3048
  if (separator >= 0) {
2961
3049
  spaceName = decodeAddressSpace(value.substring(0, separator));
2962
3050
  offset = value.substring(separator + 3);
2963
3051
  }
2964
- else if (value.startsWith("0x")) {
3052
+ else if (value.startsWith("0x") || value.startsWith("0X")) {
2965
3053
  offset = value.substring(2);
2966
3054
  }
2967
- if (!offset.matches("[0-9A-Fa-f]+")) {
3055
+ if (!isHexadecimal(offset, 0, offset.length())) {
2968
3056
  return null;
2969
3057
  }
2970
3058
  AddressSpace space = spaceName == null
2971
3059
  ? currentProgram.getAddressFactory().getDefaultAddressSpace()
2972
3060
  : currentProgram.getAddressFactory().getAddressSpace(spaceName);
2973
- return space == null ? null : space.getAddress(offset);
2974
- }
3061
+ if (space == null) return null;
3062
+ Address address = space.getAddress(offset);
3063
+ BigInteger requestedOffset = new BigInteger(offset, 16);
3064
+ BigInteger parsedOffset = new BigInteger(Long.toUnsignedString(address.getOffset()));
3065
+ if (!requestedOffset.equals(parsedOffset))
3066
+ throw new RequestFailure("invalid_request",
3067
+ "Ghidra address offset cannot be represented without truncation in space " +
3068
+ space.getName() + ": requested " + value + ", parsed " + canonicalAddress(address));
3069
+ return address;
3070
+ }
3071
+ catch (RequestFailure failure) { throw failure; }
2975
3072
  catch (Exception exception) {
2976
3073
  return null;
2977
3074
  }
@@ -3055,9 +3152,29 @@ public final class ReaGhidraBridge extends HeadlessScript {
3055
3152
  );
3056
3153
  }
3057
3154
  catch (PatternSyntaxException exception) {
3058
- throw new RequestFailure("invalid_request", "Invalid regex pattern");
3155
+ // Java wraps compiler stack exhaustion in PatternSyntaxException
3156
+ // without retaining its cause. This producer reason is not bad syntax.
3157
+ if (exception.getDescription().equals("Stack overflow during pattern compilation"))
3158
+ throw regexStackExhausted(expression, "compiling");
3159
+ throw new RequestFailure("invalid_request", "Invalid regex pattern " + expression + ": " + exception.getDescription() + " at index " + exception.getIndex());
3160
+ }
3161
+ catch (StackOverflowError exhausted) {
3162
+ throw regexStackExhausted(expression, "compiling");
3059
3163
  }
3060
- return value -> pattern.matcher(value).find();
3164
+ return value -> {
3165
+ try {
3166
+ return pattern.matcher(value).find();
3167
+ }
3168
+ catch (StackOverflowError exhausted) {
3169
+ throw regexStackExhausted(expression, "matching");
3170
+ }
3171
+ };
3172
+ }
3173
+
3174
+ private static RequestFailure regexStackExhausted(String expression, String stage) {
3175
+ return new RequestFailure("regex_stack_exhausted",
3176
+ "Ghidra's Java regex engine exhausted its stack while " + stage +
3177
+ " pattern " + expression + ". Use literal mode or simplify the regex; the session remains usable.");
3061
3178
  }
3062
3179
 
3063
3180
  private static SessionDescriptor readDescriptor(Path path) throws IOException {
@@ -3114,7 +3231,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
3114
3231
  private void requireDocument(JsonObject params) {
3115
3232
  String document = optionalString(params, "document");
3116
3233
  if (document != null && !document.equals(currentProgram.getName())) {
3117
- throw new RequestFailure("not_found", "Unknown Ghidra Program identity");
3234
+ throw new RequestFailure("not_found", "Unknown Ghidra Program identity: " + document + "; active program: " + currentProgram.getName());
3118
3235
  }
3119
3236
  }
3120
3237
 
@@ -3226,7 +3343,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
3226
3343
 
3227
3344
  private static void writeResponse(BufferedWriter writer, JsonObject response) throws IOException {
3228
3345
  String encoded = GSON.toJson(response);
3229
- writer.write(encoded);
3346
+ // Gson leaves UTF-16 surrogates literal. Escape them in JSON so even
3347
+ // diagnostics quoting ill-formed caller text remain lossless UTF-8.
3348
+ int start = 0;
3349
+ for (int index = 0; index < encoded.length(); index++) {
3350
+ if (!Character.isSurrogate(encoded.charAt(index))) continue;
3351
+ writer.write(encoded, start, index - start);
3352
+ writer.write("\\u" + Integer.toHexString(encoded.charAt(index)));
3353
+ start = index + 1;
3354
+ }
3355
+ writer.write(encoded, start, encoded.length() - start);
3230
3356
  writer.newLine();
3231
3357
  writer.flush();
3232
3358
  }