rea-agents 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -650
- package/bridge/mitmproxy/capture.py +210 -0
- package/bridge/native/rea_lldb_tracer.py +303 -0
- package/bridge/process/ProcessRunTokenReader.swift +263 -0
- package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
- package/bridge/pwndbg/core_context.py +101 -0
- package/bridge/pwndbg/launch.py +39 -0
- package/bridge/pwndbg/launch_impl.py +34 -0
- package/bridge/pwntools/decoder_runtime.py +59 -0
- package/bridge/pwntools/layout.py +39 -0
- package/bridge/pwntools/layout_impl.py +309 -0
- package/bridge/pwntools/recorded_crash.py +39 -0
- package/bridge/pwntools/recorded_crash_impl.py +143 -0
- package/dist/android/JadxProvider.js +1 -0
- package/dist/application/CapabilityInventory.js +21 -0
- package/dist/application/DirectAnalysis.js +97 -23
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +132 -0
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/binary/AnalysisSnapshotCache.js +49 -6
- package/dist/application/binary/BinarySession.js +38 -10
- package/dist/application/binary/BinarySessionOpen.js +16 -3
- package/dist/application/binary/BinarySessionRecords.js +20 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +57 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +60 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +62 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +15 -2
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +42 -23
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +74 -24
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +23 -10
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +145 -70
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +5 -5
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +10 -10
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +4 -4
- package/dist/artifacts/ArtifactProvider.js +30 -3
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/MachoLoadCommandReader.js +294 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +3 -3
- package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
- package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
- package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +3 -3
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureEventHandlers.js +90 -2
- package/dist/browser/CdpCaptureEvents.js +9 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +12 -3
- package/dist/browser/history/CaptureFailures.js +101 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +12 -0
- package/dist/browser/history/HarCapture.js +165 -0
- package/dist/browser/history/HarCaptureAdapter.js +20 -0
- package/dist/browser/history/HarCaptureProcess.js +57 -0
- package/dist/browser/history/HarJson.js +91 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +186 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/artifactCommands.js +26 -1
- package/dist/cli/binaryDiagnosticsCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +8 -8
- package/dist/cli/electronCommands.js +16 -9
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +16 -3
- package/dist/cli/jsonOutput.js +133 -0
- package/dist/cli/nativeCallCommands.js +35 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/streamedJsonOutput.js +56 -0
- package/dist/cli/utilityCommands.js +2 -0
- package/dist/cli/webNetworkCaptureCommands.js +40 -0
- package/dist/cli.js +9 -3
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -0
- package/dist/cliJsonInput.js +30 -1
- package/dist/cliOutput.js +21 -6
- package/dist/composition/binaryDiagnostics.js +8 -0
- package/dist/composition/evm.js +4 -0
- package/dist/composition/webNetworkCaptures.js +6 -0
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/managed/managedToolContracts.js +7 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +17 -1
- package/dist/contracts/officialToolContracts.js +12 -9
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/sessionLifecycleInputs.js +22 -5
- package/dist/contracts/sessionStatusContract.js +10 -2
- package/dist/contracts/sessionToolContracts.js +8 -1
- package/dist/contracts/sessionToolSchemas.js +10 -3
- package/dist/contracts/toolContractExamples.js +1 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -1
- package/dist/contracts/toolOutputSchemaPrimitives.js +1 -1
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +15 -0
- package/dist/domain/analysisErrorCore.js +59 -5
- package/dist/domain/analysisErrorPresentation.js +29 -1
- package/dist/domain/analysisErrorProjection.js +52 -2
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +367 -0
- package/dist/domain/apple/dylibResolutionFindings.js +75 -0
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +9 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/changedBehavior.js +3 -3
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +17 -5
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +92 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +8 -1
- package/dist/domain/javascript/electronActiveObservation.js +9 -4
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptSemanticGraph.js +21 -5
- package/dist/domain/jsonValue.js +4 -0
- package/dist/domain/localPath.js +2 -0
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/nativeCallObservation.js +164 -0
- package/dist/domain/native/objcSwiftMetadata.js +0 -39
- package/dist/domain/native/recordedCrash.js +266 -0
- package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
- package/dist/domain/{processCapture.js → process/processCapture.js} +139 -2
- package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
- package/dist/domain/process/processCaptureParsing.js +54 -0
- package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
- package/dist/domain/{processComparison.js → process/processComparison.js} +1 -1
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +3 -3
- package/dist/domain/reconstructionVerificationSchemas.js +1 -1
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +3 -3
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
- package/dist/dotnet/ManagedMemberInspector.js +4 -2
- package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
- package/dist/dotnet/ManagedMemberRows.js +14 -3
- package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
- package/dist/dotnet/ManagedMetadataInventory.js +38 -28
- package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
- package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
- package/dist/dotnet/ManagedPeReader.js +11 -0
- package/dist/evm/EvmBytecodeCarrier.js +21 -0
- package/dist/evm/EvmWorkerLimits.js +40 -0
- package/dist/evm/EvmoleFailures.js +126 -0
- package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
- package/dist/evm/EvmoleInterfaceProvider.js +273 -0
- package/dist/evm/EvmoleInterfaceWorker.js +87 -0
- package/dist/evm/EvmoleRelease.js +16 -0
- package/dist/firmware/FirmwareCommand.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraLauncher.js +1 -0
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +1 -1
- package/dist/hopper/BridgeLauncher.js +2 -0
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +1 -0
- package/dist/native/CommandRunner.js +2 -1
- package/dist/native/LldbCallTracer.js +278 -0
- package/dist/native/NativeCallObservation.js +135 -0
- package/dist/native/NativeMacOSProvider.js +19 -3
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/pwndbg/PwndbgCoreContext.js +160 -0
- package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
- package/dist/native/pwntools/PwntoolsFailures.js +180 -0
- package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
- package/dist/native/pwntools/PwntoolsRelease.js +19 -0
- package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +101 -0
- package/dist/process/DarwinProcessRunTokenReader.js +294 -0
- package/dist/process/OwnedCommand.js +113 -0
- package/dist/process/ProcessOwnership.js +263 -33
- package/dist/process/ProcessOwnershipObservation.js +161 -24
- package/dist/process/ProviderProcess.js +30 -3
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +17 -1
- package/dist/process/capture/ProcessCaptureLifecycle.js +615 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/createServer.js +22 -0
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerBinaryDiagnosticsTools.js +17 -0
- package/dist/server/registerEvidenceTools.js +1 -1
- package/dist/server/registerEvmTools.js +17 -0
- package/dist/server/registerProcessComparisonTool.js +1 -1
- package/dist/server/registerRecordedCrashTools.js +17 -0
- package/dist/server/registerSessionTools.js +2 -2
- package/dist/server/registerWebNetworkCaptureTool.js +28 -0
- package/dist/server/sessionAvailabilityPolicy.js +3 -0
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolResult.js +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +37 -9
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +23 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
- package/third_party/README.md +60 -0
- package/third_party/evmole/LICENSE +21 -0
- package/third_party/evmole/README.md +22 -0
- package/third_party/pwndbg/LICENSE.md +21 -0
- package/third_party/pwndbg/README.md +23 -0
- package/third_party/pwntools/README.md +40 -0
- package/dist/application/AuthorizedArtifactInventory.js +0 -7
- package/dist/application/ProcessCaptureLifecycle.js +0 -299
- package/dist/application/StoreFileLock.js +0 -124
- package/dist/contracts/processCaptureExample.js +0 -2
- package/dist/domain/bytecodeProvider.js +0 -178
- package/dist/domain/customProtocolCapture.js +0 -137
- package/dist/domain/eventProcessTree.js +0 -225
- package/dist/domain/mobileApplicationInvestigation.js +0 -159
- package/dist/domain/packageAnalysis.js +0 -123
- package/dist/domain/peInspection.js +0 -197
- package/dist/domain/processCaptureParsing.js +0 -21
- package/dist/domain/protocolCapture.js +0 -217
- package/dist/domain/runtimeIdentification.js +0 -212
- package/dist/generatedMcpToolCatalog.js +0 -37
- /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
- /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
- /package/dist/domain/{processScenario.js → process/processScenario.js} +0 -0
- /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
- /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
- /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
- /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
- /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
- /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
- /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
- /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
- /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const unsignedHex = z.string().regex(/^0x(?:0|[1-9a-f][0-9a-f]{0,15})$/);
|
|
3
|
+
const index = z.number().int().nonnegative();
|
|
4
|
+
const scalar = z.union([z.string(), z.number().int()]);
|
|
5
|
+
const range = z.strictObject({ offset: unsignedHex, bytes: unsignedHex });
|
|
6
|
+
const canonicalBase64 = z
|
|
7
|
+
.string()
|
|
8
|
+
.regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?$/);
|
|
9
|
+
const name = z.strictObject({
|
|
10
|
+
display: z.string(),
|
|
11
|
+
bytes_base64: canonicalBase64.nullable(),
|
|
12
|
+
location: range.nullable(),
|
|
13
|
+
unknown_reason: z.string().nullable(),
|
|
14
|
+
});
|
|
15
|
+
/** Explicit local object selection, independent of an active disassembler target. */
|
|
16
|
+
export const inspectBinaryLayoutInputSchema = z.strictObject({
|
|
17
|
+
path: z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1)
|
|
20
|
+
.describe("Absolute filesystem path to the selected binary"),
|
|
21
|
+
});
|
|
22
|
+
/** File and linked-image evidence; numeric ELF values never pass through unsafe JSON numbers. */
|
|
23
|
+
const binaryLayoutObjectSchema = z.strictObject({
|
|
24
|
+
artifact: z.strictObject({
|
|
25
|
+
path: z.string().min(1),
|
|
26
|
+
sha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
27
|
+
bytes: index,
|
|
28
|
+
}),
|
|
29
|
+
format: z.literal("elf"),
|
|
30
|
+
architecture: z.strictObject({
|
|
31
|
+
machine: z.literal("EM_X86_64"),
|
|
32
|
+
bits: z.literal(64),
|
|
33
|
+
byte_order: z.literal("little"),
|
|
34
|
+
}),
|
|
35
|
+
image_type: z.enum(["ET_EXEC", "ET_DYN", "ET_REL"]),
|
|
36
|
+
entry_point: z.strictObject({
|
|
37
|
+
reported_value: unsignedHex,
|
|
38
|
+
meaning: z.enum(["linked-virtual-address", "not-applicable", "absent"]),
|
|
39
|
+
execution_status: z.literal("unknown"),
|
|
40
|
+
}),
|
|
41
|
+
runtime_load_base: z.null(),
|
|
42
|
+
sections: z.array(z.strictObject({
|
|
43
|
+
index,
|
|
44
|
+
name,
|
|
45
|
+
name_offset: unsignedHex,
|
|
46
|
+
type: scalar,
|
|
47
|
+
header_location: range,
|
|
48
|
+
address: unsignedHex,
|
|
49
|
+
offset: unsignedHex,
|
|
50
|
+
size: unsignedHex,
|
|
51
|
+
alignment: unsignedHex,
|
|
52
|
+
flags: unsignedHex,
|
|
53
|
+
link: index,
|
|
54
|
+
info: index,
|
|
55
|
+
entry_size: unsignedHex,
|
|
56
|
+
file_backing: z.enum(["file", "none"]),
|
|
57
|
+
})),
|
|
58
|
+
segments: z.array(z.strictObject({
|
|
59
|
+
index,
|
|
60
|
+
type: scalar,
|
|
61
|
+
header_location: range,
|
|
62
|
+
offset: unsignedHex,
|
|
63
|
+
file_size: unsignedHex,
|
|
64
|
+
memory_size: unsignedHex,
|
|
65
|
+
virtual_address: unsignedHex,
|
|
66
|
+
physical_address: unsignedHex,
|
|
67
|
+
alignment: unsignedHex,
|
|
68
|
+
flags: unsignedHex,
|
|
69
|
+
file_backing: z.enum(["file", "none"]),
|
|
70
|
+
permissions: z
|
|
71
|
+
.strictObject({
|
|
72
|
+
read: z.boolean(),
|
|
73
|
+
write: z.boolean(),
|
|
74
|
+
execute: z.boolean(),
|
|
75
|
+
})
|
|
76
|
+
.nullable(),
|
|
77
|
+
})),
|
|
78
|
+
symbols: z.array(z.strictObject({
|
|
79
|
+
table_index: index,
|
|
80
|
+
entry_index: index,
|
|
81
|
+
name,
|
|
82
|
+
name_offset: unsignedHex,
|
|
83
|
+
location: range,
|
|
84
|
+
value: unsignedHex,
|
|
85
|
+
value_meaning: z.enum([
|
|
86
|
+
"undefined",
|
|
87
|
+
"alignment",
|
|
88
|
+
"absolute-value",
|
|
89
|
+
"no-address",
|
|
90
|
+
"unknown-section-index",
|
|
91
|
+
"section-offset",
|
|
92
|
+
"tls-offset",
|
|
93
|
+
"linked-virtual-address",
|
|
94
|
+
]),
|
|
95
|
+
size: unsignedHex,
|
|
96
|
+
binding: scalar,
|
|
97
|
+
type: scalar,
|
|
98
|
+
visibility: scalar,
|
|
99
|
+
section_index: scalar,
|
|
100
|
+
})),
|
|
101
|
+
relocations: z.array(z.strictObject({
|
|
102
|
+
section_index: index,
|
|
103
|
+
entry_index: index,
|
|
104
|
+
reported_offset: unsignedHex,
|
|
105
|
+
target: z.discriminatedUnion("kind", [
|
|
106
|
+
z.strictObject({
|
|
107
|
+
kind: z.literal("section-offset"),
|
|
108
|
+
section_index: index,
|
|
109
|
+
offset: unsignedHex,
|
|
110
|
+
}),
|
|
111
|
+
z.strictObject({
|
|
112
|
+
kind: z.literal("linked-virtual-address"),
|
|
113
|
+
address: unsignedHex,
|
|
114
|
+
}),
|
|
115
|
+
z.strictObject({
|
|
116
|
+
kind: z.literal("unknown-section"),
|
|
117
|
+
reported_section_index: index,
|
|
118
|
+
offset: unsignedHex,
|
|
119
|
+
unknown_reason: z.enum([
|
|
120
|
+
"undefined-section-reference",
|
|
121
|
+
"inactive-section-header",
|
|
122
|
+
]),
|
|
123
|
+
}),
|
|
124
|
+
]),
|
|
125
|
+
location: range,
|
|
126
|
+
type: index,
|
|
127
|
+
symbol_table_index: index,
|
|
128
|
+
symbol_index: index,
|
|
129
|
+
symbol_reference_meaning: z.enum([
|
|
130
|
+
"zero-symbol-value",
|
|
131
|
+
"symbol-table-entry",
|
|
132
|
+
]),
|
|
133
|
+
addend: z
|
|
134
|
+
.string()
|
|
135
|
+
.regex(/^-?(?:0|[1-9][0-9]{0,18})$/)
|
|
136
|
+
.nullable(),
|
|
137
|
+
})),
|
|
138
|
+
packed_relative_relocations: z.array(z.strictObject({
|
|
139
|
+
section_index: index,
|
|
140
|
+
location: range,
|
|
141
|
+
encoded_bytes_base64: canonicalBase64,
|
|
142
|
+
entries: z.array(z.strictObject({ decoded_index: index, reported_offset: unsignedHex })),
|
|
143
|
+
offset_meaning: z.enum(["linked-virtual-address", "unknown"]),
|
|
144
|
+
evidence_kind: z.literal("derived"),
|
|
145
|
+
entry_source_locations: z.null(),
|
|
146
|
+
addends: z.null(),
|
|
147
|
+
})),
|
|
148
|
+
relocation_inventory_completeness: z.literal("unknown"),
|
|
149
|
+
linkage: z.strictObject({
|
|
150
|
+
needed_libraries: z.array(name),
|
|
151
|
+
interpreters: z.array(name),
|
|
152
|
+
got: z.array(z.strictObject({ display_name: z.string(), address: unsignedHex })),
|
|
153
|
+
plt: z.array(z.strictObject({ display_name: z.string(), address: unsignedHex })),
|
|
154
|
+
convenience_maps_completeness: z.literal("unknown"),
|
|
155
|
+
runtime_library_paths: z.null(),
|
|
156
|
+
}),
|
|
157
|
+
mitigations: z.strictObject({
|
|
158
|
+
evidence_kind: z.literal("inferred"),
|
|
159
|
+
position_independent: z.boolean(),
|
|
160
|
+
nx_indicator: z.boolean().nullable(),
|
|
161
|
+
executable_stack_indicator: z.boolean(),
|
|
162
|
+
stack_canary_indicator: z.boolean(),
|
|
163
|
+
relro: z.enum(["Partial", "Full"]).nullable(),
|
|
164
|
+
}),
|
|
165
|
+
diagnostics: z.strictObject({
|
|
166
|
+
stdout: z.string(),
|
|
167
|
+
stderr: z.string(),
|
|
168
|
+
truncated: z.boolean(),
|
|
169
|
+
}),
|
|
170
|
+
limitations: z.array(z.string()),
|
|
171
|
+
});
|
|
172
|
+
/** Decoder payload excludes the artifact identity observed by the owning process boundary. */
|
|
173
|
+
export const binaryLayoutPayloadSchema = binaryLayoutObjectSchema.omit({
|
|
174
|
+
artifact: true,
|
|
175
|
+
diagnostics: true,
|
|
176
|
+
});
|
|
177
|
+
/** Check source ranges again at the public boundary, independently of upstream parsing. */
|
|
178
|
+
export const binaryLayoutSchema = binaryLayoutObjectSchema.superRefine((value, context) => {
|
|
179
|
+
const size = BigInt(value.artifact.bytes);
|
|
180
|
+
const check = (offset, length, path) => {
|
|
181
|
+
const start = BigInt(offset);
|
|
182
|
+
const bytes = BigInt(length);
|
|
183
|
+
if (start > size || bytes > size - start)
|
|
184
|
+
context.addIssue({
|
|
185
|
+
code: "custom",
|
|
186
|
+
path,
|
|
187
|
+
message: "Reported file-backed range lies outside the selected artifact.",
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
const checkLocation = (where, path) => check(where.offset, where.bytes, path);
|
|
191
|
+
const checkName = (reported, path) => {
|
|
192
|
+
if (reported.location !== null)
|
|
193
|
+
checkLocation(reported.location, [...path, "location"]);
|
|
194
|
+
};
|
|
195
|
+
const expectedEntryMeaning = value.image_type === "ET_REL"
|
|
196
|
+
? "not-applicable"
|
|
197
|
+
: value.entry_point.reported_value === "0x0"
|
|
198
|
+
? "absent"
|
|
199
|
+
: "linked-virtual-address";
|
|
200
|
+
if (value.entry_point.meaning !== expectedEntryMeaning)
|
|
201
|
+
context.addIssue({
|
|
202
|
+
code: "custom",
|
|
203
|
+
path: ["entry_point", "meaning"],
|
|
204
|
+
message: "Entry meaning must distinguish zero/unused fields from an actual linked address.",
|
|
205
|
+
});
|
|
206
|
+
for (const [index, section] of value.sections.entries()) {
|
|
207
|
+
if ((section.type === "SHT_SYMTAB" || section.type === "SHT_DYNSYM") &&
|
|
208
|
+
value.sections[section.link]?.type !== "SHT_STRTAB")
|
|
209
|
+
context.addIssue({
|
|
210
|
+
code: "custom",
|
|
211
|
+
path: ["sections", index, "link"],
|
|
212
|
+
message: "Symbol tables must link to an existing string-table section.",
|
|
213
|
+
});
|
|
214
|
+
if (section.index !== index)
|
|
215
|
+
context.addIssue({
|
|
216
|
+
code: "custom",
|
|
217
|
+
path: ["sections", index, "index"],
|
|
218
|
+
message: "Complete section order must preserve original producer indices.",
|
|
219
|
+
});
|
|
220
|
+
checkLocation(section.header_location, [
|
|
221
|
+
"sections",
|
|
222
|
+
index,
|
|
223
|
+
"header_location",
|
|
224
|
+
]);
|
|
225
|
+
checkName(section.name, ["sections", index, "name"]);
|
|
226
|
+
if (section.file_backing === "file")
|
|
227
|
+
check(section.offset, section.size, ["sections", index]);
|
|
228
|
+
}
|
|
229
|
+
for (const [index, segment] of value.segments.entries()) {
|
|
230
|
+
if (segment.index !== index)
|
|
231
|
+
context.addIssue({
|
|
232
|
+
code: "custom",
|
|
233
|
+
path: ["segments", index, "index"],
|
|
234
|
+
message: "Complete segment order must preserve original producer indices.",
|
|
235
|
+
});
|
|
236
|
+
checkLocation(segment.header_location, [
|
|
237
|
+
"segments",
|
|
238
|
+
index,
|
|
239
|
+
"header_location",
|
|
240
|
+
]);
|
|
241
|
+
const hasFileBytes = segment.type !== "PT_NULL" && BigInt(segment.file_size) !== 0n;
|
|
242
|
+
if (segment.file_backing !== (hasFileBytes ? "file" : "none"))
|
|
243
|
+
context.addIssue({
|
|
244
|
+
code: "custom",
|
|
245
|
+
path: ["segments", index, "file_backing"],
|
|
246
|
+
message: "File backing must follow the reported segment type and file size.",
|
|
247
|
+
});
|
|
248
|
+
if ((segment.type === "PT_NULL") !== (segment.permissions === null))
|
|
249
|
+
context.addIssue({
|
|
250
|
+
code: "custom",
|
|
251
|
+
path: ["segments", index, "permissions"],
|
|
252
|
+
message: "Unused PT_NULL flags have no permission meaning; other segment flags retain their interpretation.",
|
|
253
|
+
});
|
|
254
|
+
if (hasFileBytes)
|
|
255
|
+
check(segment.offset, segment.file_size, ["segments", index]);
|
|
256
|
+
}
|
|
257
|
+
for (const [index, symbol] of value.symbols.entries()) {
|
|
258
|
+
checkLocation(symbol.location, ["symbols", index, "location"]);
|
|
259
|
+
checkName(symbol.name, ["symbols", index, "name"]);
|
|
260
|
+
}
|
|
261
|
+
for (const [index, relocation] of value.relocations.entries())
|
|
262
|
+
checkLocation(relocation.location, ["relocations", index, "location"]);
|
|
263
|
+
validateRelocationReferences(value, context);
|
|
264
|
+
validatePackedRelativeTables(value, context, checkLocation);
|
|
265
|
+
for (const facet of ["needed_libraries", "interpreters"])
|
|
266
|
+
for (const [index, reported] of value.linkage[facet].entries())
|
|
267
|
+
checkName(reported, ["linkage", facet, index]);
|
|
268
|
+
});
|
|
269
|
+
const validateRelocationReferences = (value, context) => {
|
|
270
|
+
const symbols = new Set(value.symbols.map((symbol) => `${symbol.table_index}:${symbol.entry_index}`));
|
|
271
|
+
for (const [index, relocation] of value.relocations.entries()) {
|
|
272
|
+
const owner = value.sections[relocation.section_index];
|
|
273
|
+
const target = relocation.target;
|
|
274
|
+
const targetMatches = value.image_type === "ET_REL"
|
|
275
|
+
? target.kind === "section-offset"
|
|
276
|
+
? target.section_index !== 0 &&
|
|
277
|
+
target.section_index === owner?.info &&
|
|
278
|
+
value.sections[target.section_index] !== undefined &&
|
|
279
|
+
value.sections[target.section_index]?.type !== "SHT_NULL" &&
|
|
280
|
+
target.offset === relocation.reported_offset
|
|
281
|
+
: target.kind === "unknown-section" &&
|
|
282
|
+
target.reported_section_index === owner?.info &&
|
|
283
|
+
target.offset === relocation.reported_offset &&
|
|
284
|
+
(target.reported_section_index === 0
|
|
285
|
+
? target.unknown_reason === "undefined-section-reference"
|
|
286
|
+
: value.sections[target.reported_section_index]?.type ===
|
|
287
|
+
"SHT_NULL" &&
|
|
288
|
+
target.unknown_reason === "inactive-section-header")
|
|
289
|
+
: target.kind === "linked-virtual-address" &&
|
|
290
|
+
target.address === relocation.reported_offset;
|
|
291
|
+
if (!targetMatches)
|
|
292
|
+
context.addIssue({
|
|
293
|
+
code: "custom",
|
|
294
|
+
path: ["relocations", index, "target"],
|
|
295
|
+
message: "Relocation target must preserve its reported offset and owner reference; SHN_UNDEF and inactive headers remain unknown rather than resolved sections.",
|
|
296
|
+
});
|
|
297
|
+
const table = value.sections[relocation.symbol_table_index];
|
|
298
|
+
const tableExists = relocation.symbol_table_index !== 0 &&
|
|
299
|
+
(table?.type === "SHT_SYMTAB" || table?.type === "SHT_DYNSYM");
|
|
300
|
+
const positiveReferenceExists = tableExists &&
|
|
301
|
+
BigInt(table.entry_size) >= 24n &&
|
|
302
|
+
BigInt(relocation.symbol_index) <
|
|
303
|
+
BigInt(table.size) / BigInt(table.entry_size) &&
|
|
304
|
+
symbols.has(`${relocation.symbol_table_index}:${relocation.symbol_index}`);
|
|
305
|
+
if ((owner?.type !== "SHT_REL" && owner?.type !== "SHT_RELA") ||
|
|
306
|
+
owner.link !== relocation.symbol_table_index ||
|
|
307
|
+
(relocation.symbol_table_index !== 0 && !tableExists) ||
|
|
308
|
+
(relocation.symbol_index !== 0 && !positiveReferenceExists) ||
|
|
309
|
+
relocation.symbol_reference_meaning !==
|
|
310
|
+
(relocation.symbol_index === 0
|
|
311
|
+
? "zero-symbol-value"
|
|
312
|
+
: "symbol-table-entry"))
|
|
313
|
+
context.addIssue({
|
|
314
|
+
code: "custom",
|
|
315
|
+
path: ["relocations", index],
|
|
316
|
+
message: "Relocation must preserve its REL/RELA owner and resolve positive symbol indices through the linked symbol table; index zero uses a zero symbol value.",
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const validatePackedRelativeTables = (value, context, checkLocation) => {
|
|
321
|
+
for (const [tableIndex, table,] of value.packed_relative_relocations.entries()) {
|
|
322
|
+
checkLocation(table.location, [
|
|
323
|
+
"packed_relative_relocations",
|
|
324
|
+
tableIndex,
|
|
325
|
+
"location",
|
|
326
|
+
]);
|
|
327
|
+
const encodedBytes = (table.encoded_bytes_base64.length * 3) / 4 -
|
|
328
|
+
(table.encoded_bytes_base64.endsWith("==")
|
|
329
|
+
? 2
|
|
330
|
+
: table.encoded_bytes_base64.endsWith("=")
|
|
331
|
+
? 1
|
|
332
|
+
: 0);
|
|
333
|
+
if (!Number.isInteger(encodedBytes) ||
|
|
334
|
+
BigInt(encodedBytes) !== BigInt(table.location.bytes))
|
|
335
|
+
context.addIssue({
|
|
336
|
+
code: "custom",
|
|
337
|
+
path: ["packed_relative_relocations", tableIndex],
|
|
338
|
+
message: "Complete packed table bytes must match its original file range.",
|
|
339
|
+
});
|
|
340
|
+
const section = value.sections[table.section_index];
|
|
341
|
+
if (section?.type !== "SHT_RELR" ||
|
|
342
|
+
section.offset !== table.location.offset ||
|
|
343
|
+
section.size !== table.location.bytes)
|
|
344
|
+
context.addIssue({
|
|
345
|
+
code: "custom",
|
|
346
|
+
path: ["packed_relative_relocations", tableIndex, "section_index"],
|
|
347
|
+
message: "Packed relative evidence must retain its original RELR section identity and range.",
|
|
348
|
+
});
|
|
349
|
+
for (const [decoded, entry] of table.entries.entries())
|
|
350
|
+
if (entry.decoded_index !== decoded)
|
|
351
|
+
context.addIssue({
|
|
352
|
+
code: "custom",
|
|
353
|
+
path: ["packed_relative_relocations", tableIndex, "entries", decoded],
|
|
354
|
+
message: "Decoded offsets must preserve upstream iterator order.",
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const hexSchema = z.string().regex(/^0x[0-9a-f]+$/u);
|
|
3
|
+
/** Objective-C class names and selectors never contain spaces or brackets. */
|
|
4
|
+
const objcName = z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1)
|
|
7
|
+
.regex(/^[^\s[\]]+$/u, "Use the bare name without spaces or brackets");
|
|
8
|
+
const functionBreakpoint = {
|
|
9
|
+
kind: z.literal("function"),
|
|
10
|
+
name: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.describe("Exact symbol name, such as `open`, a C++ or mangled Swift symbol, or `-[NSString length]`."),
|
|
14
|
+
};
|
|
15
|
+
const objcMethodBreakpoint = {
|
|
16
|
+
kind: z.literal("objc-method"),
|
|
17
|
+
selector: objcName.describe("Selector such as `dataTaskWithRequest:completionHandler:`."),
|
|
18
|
+
};
|
|
19
|
+
/** One function or Objective-C method whose entries are observed. */
|
|
20
|
+
export const nativeCallBreakpointSchema = z.discriminatedUnion("kind", [
|
|
21
|
+
z.strictObject({
|
|
22
|
+
...functionBreakpoint,
|
|
23
|
+
module: z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Image file name that defines the symbol, such as `libsystem_kernel.dylib`; omit to match every image."),
|
|
28
|
+
}),
|
|
29
|
+
z.strictObject({
|
|
30
|
+
...objcMethodBreakpoint,
|
|
31
|
+
class_name: objcName
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Implementing class; omit to match every class."),
|
|
34
|
+
method_type: z.enum(["instance", "class", "any"]).default("any"),
|
|
35
|
+
}),
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Launch the active Mach-O as an owned process under LLDB and observe calls.
|
|
39
|
+
* Duration and event bounds keep runtime observation finite.
|
|
40
|
+
*/
|
|
41
|
+
export const nativeCallObservationInputSchema = z.strictObject({
|
|
42
|
+
breakpoints: z.array(nativeCallBreakpointSchema).min(1),
|
|
43
|
+
arguments: z.array(z.string()).default([]),
|
|
44
|
+
environment: z
|
|
45
|
+
.record(z
|
|
46
|
+
.string()
|
|
47
|
+
.min(1)
|
|
48
|
+
.regex(/^[^=\0]+$/u, "Environment names cannot contain '=' or NUL"), z.string().regex(/^[^\0]*$/u, "Environment values cannot contain NUL"))
|
|
49
|
+
.default({})
|
|
50
|
+
.describe("Overrides on top of the environment REA runs with."),
|
|
51
|
+
working_directory: z.string().min(1).optional(),
|
|
52
|
+
duration_ms: z
|
|
53
|
+
.number()
|
|
54
|
+
.int()
|
|
55
|
+
.min(100)
|
|
56
|
+
.max(600_000)
|
|
57
|
+
.default(10_000)
|
|
58
|
+
.describe("Observation window; the process is killed if it is still running."),
|
|
59
|
+
max_events: z
|
|
60
|
+
.number()
|
|
61
|
+
.int()
|
|
62
|
+
.min(1)
|
|
63
|
+
.max(100_000)
|
|
64
|
+
.default(1_000)
|
|
65
|
+
.describe("Stop observing and kill the process after this many recorded entries."),
|
|
66
|
+
argument_registers: z
|
|
67
|
+
.number()
|
|
68
|
+
.int()
|
|
69
|
+
.min(0)
|
|
70
|
+
.max(8)
|
|
71
|
+
.default(4)
|
|
72
|
+
.describe("Integer argument registers to record per entry (arm64 has 8, x86_64 has 6)."),
|
|
73
|
+
backtrace_frames: z
|
|
74
|
+
.number()
|
|
75
|
+
.int()
|
|
76
|
+
.min(0)
|
|
77
|
+
.max(64)
|
|
78
|
+
.default(0)
|
|
79
|
+
.describe("Caller frames to record per entry."),
|
|
80
|
+
});
|
|
81
|
+
/** A code address with the image and symbol LLDB attributes to it. */
|
|
82
|
+
export const nativeCodeLocationSchema = z.strictObject({
|
|
83
|
+
load_address: hexSchema,
|
|
84
|
+
file_address: hexSchema.nullable(),
|
|
85
|
+
module: z.string().nullable(),
|
|
86
|
+
module_path: z.string().nullable(),
|
|
87
|
+
symbol: z.string().nullable(),
|
|
88
|
+
});
|
|
89
|
+
/** One observed entry into a requested function or method. */
|
|
90
|
+
export const nativeCallEventSchema = z.strictObject({
|
|
91
|
+
sequence: z.number().int().nonnegative(),
|
|
92
|
+
elapsed_ms: z.number().nonnegative(),
|
|
93
|
+
thread_id: z.number().int().nonnegative(),
|
|
94
|
+
breakpoint_index: z.number().int().nonnegative(),
|
|
95
|
+
...nativeCodeLocationSchema.shape,
|
|
96
|
+
/** Dynamic class of an instance-method receiver, read without running code. */
|
|
97
|
+
receiver_class: z.string().nullable(),
|
|
98
|
+
/** Selector string read from the `_cmd` register of an Objective-C method. */
|
|
99
|
+
selector: z.string().nullable(),
|
|
100
|
+
registers: z.array(z.strictObject({ name: z.string(), value: hexSchema })),
|
|
101
|
+
backtrace: z.array(nativeCodeLocationSchema),
|
|
102
|
+
});
|
|
103
|
+
const capturedOutputSchema = z.strictObject({
|
|
104
|
+
text: z.string(),
|
|
105
|
+
bytes: z.number().int().nonnegative(),
|
|
106
|
+
truncated: z.boolean(),
|
|
107
|
+
});
|
|
108
|
+
/** Observed calls, the process lifecycle, and breakpoint resolution. */
|
|
109
|
+
export const nativeCallObservationResultSchema = z.strictObject({
|
|
110
|
+
target: z.strictObject({
|
|
111
|
+
path: z.string(),
|
|
112
|
+
sha256: z.string().regex(/^[0-9a-f]{64}$/u),
|
|
113
|
+
architecture: z.string(),
|
|
114
|
+
arguments: z.array(z.string()),
|
|
115
|
+
working_directory: z.string().nullable(),
|
|
116
|
+
}),
|
|
117
|
+
debugger: z.strictObject({
|
|
118
|
+
path: z.string(),
|
|
119
|
+
sha256: z.string().regex(/^[0-9a-f]{64}$/u),
|
|
120
|
+
version: z.string().nullable(),
|
|
121
|
+
}),
|
|
122
|
+
process: z.strictObject({
|
|
123
|
+
pid: z.number().int().positive(),
|
|
124
|
+
outcome: z.enum([
|
|
125
|
+
"exited",
|
|
126
|
+
"duration-elapsed",
|
|
127
|
+
"event-limit",
|
|
128
|
+
"stop-limit",
|
|
129
|
+
]),
|
|
130
|
+
exit_status: z.number().int().nullable(),
|
|
131
|
+
exit_description: z.string().nullable(),
|
|
132
|
+
/** REA confirmed the process is gone when observation ended. */
|
|
133
|
+
terminated: z.boolean(),
|
|
134
|
+
elapsed_ms: z.number().nonnegative(),
|
|
135
|
+
stdout: capturedOutputSchema,
|
|
136
|
+
stderr: capturedOutputSchema,
|
|
137
|
+
/** Signal and exception stops LLDB reported; the process continued past each. */
|
|
138
|
+
other_stops: z.array(z.string()),
|
|
139
|
+
}),
|
|
140
|
+
breakpoints: z.array(z.strictObject({
|
|
141
|
+
index: z.number().int().nonnegative(),
|
|
142
|
+
request: z.discriminatedUnion("kind", [
|
|
143
|
+
z.strictObject({
|
|
144
|
+
...functionBreakpoint,
|
|
145
|
+
module: z.string().nullable(),
|
|
146
|
+
}),
|
|
147
|
+
z.strictObject({
|
|
148
|
+
...objcMethodBreakpoint,
|
|
149
|
+
class_name: z.string().nullable(),
|
|
150
|
+
method_type: z.enum(["instance", "class", "any"]),
|
|
151
|
+
}),
|
|
152
|
+
]),
|
|
153
|
+
location_count: z.number().int().nonnegative(),
|
|
154
|
+
locations: z.array(nativeCodeLocationSchema),
|
|
155
|
+
})),
|
|
156
|
+
events: z.array(nativeCallEventSchema),
|
|
157
|
+
coverage: z.strictObject({
|
|
158
|
+
status: z.enum(["complete", "partial"]),
|
|
159
|
+
event_limit_reached: z.boolean(),
|
|
160
|
+
/** Requests that matched no code in any image loaded while observing. */
|
|
161
|
+
unresolved_breakpoints: z.array(z.number().int().nonnegative()),
|
|
162
|
+
}),
|
|
163
|
+
limitations: z.array(z.string()),
|
|
164
|
+
});
|
|
@@ -419,42 +419,3 @@ const parseMetadataAddress = (address) => {
|
|
|
419
419
|
const value = Number.parseInt(match[1], 16);
|
|
420
420
|
return Number.isSafeInteger(value) ? value : null;
|
|
421
421
|
};
|
|
422
|
-
/** Check if a selector name looks like a getter. */
|
|
423
|
-
export function isGetterSelector(selector) {
|
|
424
|
-
return /^[a-z][a-zA-Z0-9_]*$/u.test(selector) && !selector.includes(":");
|
|
425
|
-
}
|
|
426
|
-
/** Check if a selector name looks like a setter. */
|
|
427
|
-
export function isSetterSelector(selector) {
|
|
428
|
-
return selector.startsWith("set") && selector.endsWith(":");
|
|
429
|
-
}
|
|
430
|
-
/** Extract property name from a getter/setter selector. */
|
|
431
|
-
export function propertyNameFromSelector(selector) {
|
|
432
|
-
if (isSetterSelector(selector)) {
|
|
433
|
-
const inner = selector.slice(3, -1);
|
|
434
|
-
return inner.charAt(0).toLowerCase() + inner.slice(1);
|
|
435
|
-
}
|
|
436
|
-
if (isGetterSelector(selector)) {
|
|
437
|
-
return selector;
|
|
438
|
-
}
|
|
439
|
-
return null;
|
|
440
|
-
}
|
|
441
|
-
/** Count ObjC methods by type. */
|
|
442
|
-
export function countMethodsByType(methods) {
|
|
443
|
-
return {
|
|
444
|
-
instance: methods.filter((m) => m.method_type === "instance").length,
|
|
445
|
-
class: methods.filter((m) => m.method_type === "class").length,
|
|
446
|
-
ivar_getter: methods.filter((m) => m.method_type === "ivar_getter").length,
|
|
447
|
-
ivar_setter: methods.filter((m) => m.method_type === "ivar_setter").length,
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
/** Get all Swift declarations of a specific kind. */
|
|
451
|
-
export function swiftDeclsByKind(decls, kind) {
|
|
452
|
-
return decls.filter((d) => d.kind === kind);
|
|
453
|
-
}
|
|
454
|
-
/** Check if a database save preserved all expected items. */
|
|
455
|
-
export function isDbSaveComplete(result, expectedNames, expectedComments, expectedBookmarks) {
|
|
456
|
-
return (result.succeeded &&
|
|
457
|
-
result.preserved_names >= expectedNames &&
|
|
458
|
-
result.preserved_comments >= expectedComments &&
|
|
459
|
-
result.preserved_bookmarks >= expectedBookmarks);
|
|
460
|
-
}
|