rea-agents 5.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.
- package/README.md +168 -655
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +208 -0
- package/bridge/native/rea_lldb_tracer.py +839 -0
- package/bridge/process/ProcessRunTokenReader.swift +297 -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 +147 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +20 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +27 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +97 -33
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +24 -12
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +134 -0
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
- package/dist/application/binary/BinarySession.js +131 -76
- package/dist/application/binary/BinarySessionOpen.js +19 -6
- package/dist/application/binary/BinarySessionRecords.js +45 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +64 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
- 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 +27 -5
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +42 -5
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
- 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 +14 -17
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +165 -12
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +34 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +137 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +17 -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 +92 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- 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 +78 -20
- package/dist/cli/electronCommands.js +21 -13
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +20 -3
- package/dist/cli/jsonOutput.js +38 -0
- package/dist/cli/nativeCallCommands.js +34 -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/webRuntimeCommands.js +8 -8
- package/dist/cli.js +11 -4
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -1
- package/dist/cliJsonInput.js +35 -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/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +8 -6
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +21 -3
- package/dist/contracts/officialToolContracts.js +26 -24
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +18 -5
- package/dist/contracts/sessionStatusContract.js +8 -2
- package/dist/contracts/sessionToolContracts.js +8 -3
- package/dist/contracts/sessionToolSchemas.js +8 -4
- package/dist/contracts/toolContractExamples.js +1 -2
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -1
- package/dist/contracts/toolOutputSchemaGroups.js +33 -28
- package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +22 -2
- package/dist/domain/analysisErrorCore.js +61 -5
- package/dist/domain/analysisErrorPresentation.js +95 -12
- package/dist/domain/analysisErrorProjection.js +148 -19
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +478 -0
- package/dist/domain/apple/dylibResolutionFindings.js +77 -0
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +5 -2
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +78 -11
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +108 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +10 -4
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +37 -6
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +91 -3
- package/dist/domain/localPath.js +8 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +186 -0
- package/dist/domain/native/nativeCallPartialObservation.js +33 -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} +143 -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} +39 -5
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +3 -3
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +9 -46
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -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/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +34 -16
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +33 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +82 -84
- package/dist/native/LldbCallTracer.js +541 -0
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +194 -0
- package/dist/native/NativeMacOSProvider.js +117 -20
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +180 -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 +103 -0
- package/dist/process/DarwinProcessRunTokenReader.js +293 -0
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +118 -0
- package/dist/process/ProcessOwnership.js +431 -51
- package/dist/process/ProcessOwnershipObservation.js +209 -27
- package/dist/process/ProviderProcess.js +68 -10
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +37 -8
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +3 -5
- package/dist/server/registerEvmTools.js +15 -0
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +72 -46
- package/dist/server/registerRecordedCrashTools.js +15 -0
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +13 -5
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +26 -0
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +3 -1
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +63 -11
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +42 -9
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +32 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- 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/ghidra/GhidraDefaults.js +0 -2
- /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/{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
|
@@ -4,36 +4,72 @@ import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
|
|
|
4
4
|
import { projectPlistValue } from "../../domain/apple/plistValue.js";
|
|
5
5
|
import { omittedPrototypeKeysLimitation, parseXmlPropertyList, } from "../../domain/propertyListKeys.js";
|
|
6
6
|
import { decodeNibArchive } from "./NibArchive.js";
|
|
7
|
+
import { estimatePropertyListDecodeBytes, InterfaceBuilderDecodeBudget, InterfaceBuilderDecodeBudgetExceeded, } from "./InterfaceBuilderDecodeBudget.js";
|
|
7
8
|
import { buildInterfaceBuilderAnalysis, interfaceBuilderLimitsSchema, } from "../../domain/apple/interfaceBuilderGraph.js";
|
|
8
9
|
import { mergeNibHierarchies, projectNibViewHierarchy, } from "./NibViewHierarchy.js";
|
|
9
10
|
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
|
10
|
-
|
|
11
|
+
import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
|
|
12
|
+
const MAX_AGGREGATE_INPUT_BYTES = 32 * 1024 * 1024;
|
|
13
|
+
const MAX_AGGREGATE_DECODE_BYTES = 256 * 1024 * 1024;
|
|
14
|
+
const MAX_REPORTED_OMITTED_ARCHIVES = 64;
|
|
11
15
|
/** Decode compiled Interface Builder archives from a local app bundle. */
|
|
12
16
|
export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
13
17
|
const limits = interfaceBuilderLimitsSchema.parse(input.limits ?? {});
|
|
14
18
|
const reader = new DirectoryArtifactReader(input.bundlePath);
|
|
15
19
|
const documents = [];
|
|
16
20
|
const invalid = [];
|
|
21
|
+
const omittedArchives = [];
|
|
22
|
+
let unreportedOmittedArchives = 0;
|
|
17
23
|
const incompleteHierarchies = new Map();
|
|
18
24
|
const prototypeKeyOmissions = new Map();
|
|
19
25
|
let omitted = 0;
|
|
20
26
|
let attempted = 0;
|
|
27
|
+
let candidates = 0;
|
|
28
|
+
let aggregateInputBytes = 0;
|
|
29
|
+
const decodeBudget = new InterfaceBuilderDecodeBudget(MAX_AGGREGATE_DECODE_BYTES);
|
|
30
|
+
const recordOmittedArchive = (path, reason) => {
|
|
31
|
+
if (omittedArchives.length < MAX_REPORTED_OMITTED_ARCHIVES)
|
|
32
|
+
omittedArchives.push({ path, reason });
|
|
33
|
+
else
|
|
34
|
+
unreportedOmittedArchives += 1;
|
|
35
|
+
};
|
|
21
36
|
try {
|
|
22
37
|
for await (const entry of reader.entries(input.signal)) {
|
|
23
38
|
if (entry.kind !== "file" || !isInterfaceBuilderArchive(entry.path))
|
|
24
39
|
continue;
|
|
25
|
-
|
|
40
|
+
candidates += 1;
|
|
41
|
+
if (candidates > limits.max_documents) {
|
|
26
42
|
omitted += 1;
|
|
43
|
+
recordOmittedArchive(entry.path, "max_documents");
|
|
27
44
|
continue;
|
|
28
45
|
}
|
|
29
|
-
attempted += 1;
|
|
30
46
|
try {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
const remainingInputBytes = MAX_AGGREGATE_INPUT_BYTES - aggregateInputBytes;
|
|
48
|
+
if (entry.declaredSize !== null &&
|
|
49
|
+
entry.declaredSize > remainingInputBytes) {
|
|
50
|
+
omitted += 1;
|
|
51
|
+
recordOmittedArchive(entry.path, "aggregate_decode_budget_exhausted");
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
attempted += 1;
|
|
55
|
+
const bytes = await readEntry(reader, entry, input.signal, remainingInputBytes);
|
|
56
|
+
aggregateInputBytes += bytes.length;
|
|
57
|
+
const isNibArchive = bytes.subarray(0, 10).toString("ascii") === "NIBArchive";
|
|
58
|
+
let nib = null;
|
|
59
|
+
let xmlText;
|
|
60
|
+
if (isNibArchive) {
|
|
61
|
+
const documentBudget = new InterfaceBuilderDecodeBudget(decodeBudget.remainingBytes);
|
|
62
|
+
nib = projectNibArchive(decodeNibArchive(bytes, documentBudget), documentBudget, limits.max_objects);
|
|
63
|
+
decodeBudget.reserve(documentBudget.usedBytes, "NIBArchive representation exceeds the aggregate Interface Builder decode budget");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
if (bytes.subarray(0, 8).toString("ascii") !== "bplist00")
|
|
67
|
+
xmlText = decodeXmlPlistText(bytes);
|
|
68
|
+
const decodedReservation = estimatePropertyListDecodeBytes(bytes, decodeBudget.remainingBytes, xmlText);
|
|
69
|
+
decodeBudget.reserve(decodedReservation, "plist representation exceeds the aggregate Interface Builder decode budget");
|
|
70
|
+
}
|
|
35
71
|
const { value: raw, omittedPrototypeKeys } = nib === null
|
|
36
|
-
? decodePlist(bytes)
|
|
72
|
+
? decodePlist(bytes, xmlText)
|
|
37
73
|
: { value: nib.raw, omittedPrototypeKeys: 0 };
|
|
38
74
|
if (nib !== null && nib.omitted > 0)
|
|
39
75
|
incompleteHierarchies.set(entry.path, nib.omitted);
|
|
@@ -52,6 +88,11 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
52
88
|
catch (cause) {
|
|
53
89
|
if (input.signal?.aborted === true)
|
|
54
90
|
throw cause;
|
|
91
|
+
if (cause instanceof InterfaceBuilderDecodeBudgetExceeded) {
|
|
92
|
+
omitted += 1;
|
|
93
|
+
recordOmittedArchive(entry.path, cause.reason);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
55
96
|
invalid.push(`${entry.path}: ${cause instanceof Error ? cause.message : "archive decode failed"}`);
|
|
56
97
|
}
|
|
57
98
|
}
|
|
@@ -69,13 +110,17 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
69
110
|
incompleteHierarchies,
|
|
70
111
|
prototypeKeyOmissions,
|
|
71
112
|
invalid,
|
|
113
|
+
omittedArchives,
|
|
114
|
+
unreportedOmittedArchives,
|
|
72
115
|
attempted,
|
|
73
116
|
omitted,
|
|
74
117
|
});
|
|
75
118
|
};
|
|
76
119
|
const finalizeHierarchyCoverage = (result, counts) => {
|
|
77
|
-
const { incompleteHierarchies, prototypeKeyOmissions, invalid } = counts;
|
|
78
|
-
const archiveDecodePartial = invalid.length > 0 ||
|
|
120
|
+
const { incompleteHierarchies, prototypeKeyOmissions, invalid, omittedArchives, unreportedOmittedArchives, } = counts;
|
|
121
|
+
const archiveDecodePartial = invalid.length > 0 ||
|
|
122
|
+
prototypeKeyOmissions.size > 0 ||
|
|
123
|
+
omittedArchives.length > 0;
|
|
79
124
|
return {
|
|
80
125
|
...result,
|
|
81
126
|
documents: result.documents.map((document) => ({
|
|
@@ -102,11 +147,17 @@ const finalizeHierarchyCoverage = (result, counts) => {
|
|
|
102
147
|
status: archiveDecodePartial
|
|
103
148
|
? "partial"
|
|
104
149
|
: "complete",
|
|
105
|
-
reason:
|
|
106
|
-
? "
|
|
107
|
-
:
|
|
108
|
-
? "
|
|
109
|
-
:
|
|
150
|
+
reason: omittedArchives.some(({ reason }) => reason === "aggregate_decode_budget_exhausted")
|
|
151
|
+
? "aggregate_decode_budget_exhausted"
|
|
152
|
+
: omittedArchives.some(({ reason }) => reason === "max_documents")
|
|
153
|
+
? "document_limit_reached"
|
|
154
|
+
: omittedArchives.length > 0
|
|
155
|
+
? "archive_decode_budget_exhausted"
|
|
156
|
+
: invalid.length > 0
|
|
157
|
+
? "one_or_more_archives_invalid"
|
|
158
|
+
: prototypeKeyOmissions.size > 0
|
|
159
|
+
? "dictionary_entries_omitted"
|
|
160
|
+
: null,
|
|
110
161
|
examined: counts.attempted,
|
|
111
162
|
omitted: counts.omitted,
|
|
112
163
|
},
|
|
@@ -130,27 +181,70 @@ const finalizeHierarchyCoverage = (result, counts) => {
|
|
|
130
181
|
`Some Interface Builder archives could not be decoded: ${invalid.slice(0, 16).join("; ")}`,
|
|
131
182
|
]),
|
|
132
183
|
...[...prototypeKeyOmissions].map(([path, count]) => `${path}: ${omittedPrototypeKeysLimitation(count)}`),
|
|
184
|
+
...omittedArchives.map(({ path, reason }) => `${path}: omitted because ${reason.replaceAll("_", " ")}.`),
|
|
185
|
+
...(unreportedOmittedArchives === 0
|
|
186
|
+
? []
|
|
187
|
+
: [
|
|
188
|
+
`${unreportedOmittedArchives} additional omitted archive path(s) and their reasons were not retained; reporting is bounded to ${MAX_REPORTED_OMITTED_ARCHIVES} paths.`,
|
|
189
|
+
]),
|
|
133
190
|
],
|
|
134
191
|
};
|
|
135
192
|
};
|
|
136
193
|
/** Project decoded NIB records into the same bounded graph input as ibtool. */
|
|
137
|
-
const projectNibArchive = (archive) => {
|
|
194
|
+
const projectNibArchive = (archive, budget, maxHierarchyNodes) => {
|
|
138
195
|
const byId = new Map(archive.objects.map((object) => [object.id, object]));
|
|
196
|
+
const normalizedClassNames = new Map();
|
|
197
|
+
const normalizeClassName = (value) => {
|
|
198
|
+
const known = normalizedClassNames.get(value);
|
|
199
|
+
if (known !== undefined)
|
|
200
|
+
return known;
|
|
201
|
+
const normalized = value.replace(/\0+$/u, "");
|
|
202
|
+
normalizedClassNames.set(value, normalized);
|
|
203
|
+
return normalized;
|
|
204
|
+
};
|
|
205
|
+
const decodedStrings = new Map();
|
|
206
|
+
const decodedString = (objectId, object) => {
|
|
207
|
+
if (decodedStrings.has(objectId))
|
|
208
|
+
return decodedStrings.get(objectId) ?? null;
|
|
209
|
+
const data = object.values["NS.bytes"];
|
|
210
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
211
|
+
decodedStrings.set(objectId, null);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const encoded = data.$nib_data_base64;
|
|
215
|
+
if (typeof encoded !== "string") {
|
|
216
|
+
decodedStrings.set(objectId, null);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
budget.reserve(64 + encoded.length * 2, "NIBArchive string projection exceeds the aggregate Interface Builder decode budget");
|
|
220
|
+
const value = Buffer.from(encoded, "base64").toString("utf8");
|
|
221
|
+
decodedStrings.set(objectId, value);
|
|
222
|
+
return value;
|
|
223
|
+
};
|
|
224
|
+
let projectedFields = 0;
|
|
225
|
+
for (const object of archive.objects)
|
|
226
|
+
projectedFields += Object.keys(object.values).length;
|
|
227
|
+
budget.reserve(archive.objects.length * 128 + projectedFields * 128, "NIBArchive graph projection exceeds the aggregate Interface Builder decode budget");
|
|
228
|
+
budget.reserve(archive.classes.length * 96, "NIBArchive class projection exceeds the aggregate Interface Builder decode budget");
|
|
139
229
|
const dereference = (value) => {
|
|
140
230
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
141
231
|
return value;
|
|
232
|
+
const encodedData = value.$nib_data_base64;
|
|
233
|
+
if (typeof encodedData === "string") {
|
|
234
|
+
budget.reserveBase64JsonStringOccurrence(encodedData);
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
142
237
|
const ref = value.$nib_object_ref;
|
|
143
238
|
if (typeof ref !== "number")
|
|
144
239
|
return value;
|
|
145
240
|
const target = byId.get(ref);
|
|
146
241
|
if (target === undefined)
|
|
147
242
|
return undefined;
|
|
148
|
-
if (target.class_name
|
|
149
|
-
const
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return Buffer.from(encoded, "base64").toString("utf8");
|
|
243
|
+
if (normalizeClassName(target.class_name) === "NSString") {
|
|
244
|
+
const string = decodedString(ref, target);
|
|
245
|
+
if (string !== null) {
|
|
246
|
+
budget.reserveJsonStringOccurrence(string);
|
|
247
|
+
return string;
|
|
154
248
|
}
|
|
155
249
|
}
|
|
156
250
|
return { objectID: String(ref) };
|
|
@@ -162,26 +256,30 @@ const projectNibArchive = (archive) => {
|
|
|
162
256
|
if (typeof ref !== "number")
|
|
163
257
|
return null;
|
|
164
258
|
const target = byId.get(ref);
|
|
165
|
-
|
|
166
|
-
|
|
259
|
+
if (target === undefined ||
|
|
260
|
+
normalizeClassName(target.class_name) !== "NSString")
|
|
167
261
|
return null;
|
|
168
|
-
|
|
262
|
+
const string = decodedString(ref, target);
|
|
263
|
+
if (string === null)
|
|
169
264
|
return null;
|
|
170
|
-
|
|
171
|
-
return
|
|
172
|
-
? Buffer.from(encoded, "base64").toString("utf8")
|
|
173
|
-
: null;
|
|
265
|
+
budget.reserveJsonStringOccurrence(string);
|
|
266
|
+
return string;
|
|
174
267
|
};
|
|
268
|
+
const runtimeClasses = new Map();
|
|
175
269
|
const runtimeClass = (objectId) => {
|
|
270
|
+
if (runtimeClasses.has(objectId))
|
|
271
|
+
return runtimeClasses.get(objectId) ?? null;
|
|
176
272
|
const object = byId.get(objectId);
|
|
177
273
|
if (object === undefined)
|
|
178
274
|
return null;
|
|
179
|
-
const storedClass = object.class_name
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
275
|
+
const storedClass = normalizeClassName(object.class_name);
|
|
276
|
+
const resolvedClass = storedClass === "NSClassSwapper"
|
|
277
|
+
? (referencedString(object.values.NSClassName) ?? storedClass)
|
|
278
|
+
: storedClass === "UIClassSwapper"
|
|
279
|
+
? (referencedString(object.values.UIClassName) ?? storedClass)
|
|
280
|
+
: storedClass;
|
|
281
|
+
runtimeClasses.set(objectId, resolvedClass);
|
|
282
|
+
return resolvedClass;
|
|
185
283
|
};
|
|
186
284
|
const objects = Object.fromEntries(archive.objects
|
|
187
285
|
.filter((object) => {
|
|
@@ -189,22 +287,29 @@ const projectNibArchive = (archive) => {
|
|
|
189
287
|
return !/^(?:NSObject|NSIBObjectData|NSString|NSMutableString|NSNumber|NSArray|NSMutableArray|NSSet|NSMutableSet|NSDictionary|NSMutableDictionary|NSApplication|NSNib.*Connector|UIRuntime\w*Connection)$/u.test(name);
|
|
190
288
|
})
|
|
191
289
|
.map((object) => {
|
|
192
|
-
const className = runtimeClass(object.id) ?? object.class_name
|
|
193
|
-
|
|
290
|
+
const className = runtimeClass(object.id) ?? normalizeClassName(object.class_name);
|
|
291
|
+
budget.reserveJsonStringOccurrence(className);
|
|
292
|
+
let name = className;
|
|
293
|
+
for (const [key, value] of Object.entries(object.values)) {
|
|
294
|
+
if (!/(?:title|label|identifier|accessibility|name|contents)/iu.test(key))
|
|
295
|
+
continue;
|
|
194
296
|
const resolved = dereference(value);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
297
|
+
if (typeof resolved !== "string")
|
|
298
|
+
continue;
|
|
299
|
+
name = resolved;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
budget.reserveJsonStringOccurrence(name);
|
|
198
303
|
return [
|
|
199
304
|
String(object.id),
|
|
200
305
|
{
|
|
201
306
|
customClass: className,
|
|
202
307
|
label: name,
|
|
203
308
|
objectID: String(object.id),
|
|
204
|
-
nibValues: Object.fromEntries(Object.entries(object.values).map(([key, value]) =>
|
|
205
|
-
key
|
|
206
|
-
dereference(value) ?? null
|
|
207
|
-
|
|
309
|
+
nibValues: Object.fromEntries(Object.entries(object.values).map(([key, value]) => {
|
|
310
|
+
budget.reserveJsonPropertyNameOccurrence(key);
|
|
311
|
+
return [key, dereference(value) ?? null];
|
|
312
|
+
})),
|
|
208
313
|
},
|
|
209
314
|
];
|
|
210
315
|
}));
|
|
@@ -218,7 +323,7 @@ const projectNibArchive = (archive) => {
|
|
|
218
323
|
: null;
|
|
219
324
|
};
|
|
220
325
|
for (const object of archive.objects) {
|
|
221
|
-
const className = object.class_name
|
|
326
|
+
const className = normalizeClassName(object.class_name);
|
|
222
327
|
// AppKit connectors use NS-prefixed keys; UIKit's runtime outlet and
|
|
223
328
|
// event connections use UI-prefixed keys with the same roles.
|
|
224
329
|
const uiKit = /^UIRuntime\w*Connection$/u.test(className);
|
|
@@ -235,6 +340,7 @@ const projectNibArchive = (archive) => {
|
|
|
235
340
|
: className.includes("Control") || className.includes("Event")
|
|
236
341
|
? "action"
|
|
237
342
|
: className;
|
|
343
|
+
budget.reserveJsonStringOccurrence(type);
|
|
238
344
|
const eventMask = values.UIEventMask;
|
|
239
345
|
// The source is the outlet owner or the sending control; the destination
|
|
240
346
|
// is the outlet value or the action target, and a nil target is the
|
|
@@ -249,16 +355,26 @@ const projectNibArchive = (archive) => {
|
|
|
249
355
|
});
|
|
250
356
|
}
|
|
251
357
|
let hierarchyOmitted = 0;
|
|
358
|
+
let hierarchyNodeCount = 0;
|
|
252
359
|
const hierarchyFor = (objectId, seen, depth) => {
|
|
253
360
|
if (depth > 32 || seen.has(objectId)) {
|
|
254
361
|
hierarchyOmitted += 1;
|
|
255
362
|
return null;
|
|
256
363
|
}
|
|
364
|
+
if (hierarchyNodeCount >= maxHierarchyNodes) {
|
|
365
|
+
hierarchyOmitted += 1;
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
if (!budget.tryReserve(128)) {
|
|
369
|
+
hierarchyOmitted += 1;
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
257
372
|
const object = byId.get(objectId);
|
|
258
373
|
if (object === undefined) {
|
|
259
374
|
hierarchyOmitted += 1;
|
|
260
375
|
return null;
|
|
261
376
|
}
|
|
377
|
+
hierarchyNodeCount += 1;
|
|
262
378
|
const nextSeen = new Set(seen).add(objectId);
|
|
263
379
|
const children = [];
|
|
264
380
|
for (const [key, value] of Object.entries(object.values)) {
|
|
@@ -288,7 +404,7 @@ const projectNibArchive = (archive) => {
|
|
|
288
404
|
}
|
|
289
405
|
return { objectID: String(objectId), children };
|
|
290
406
|
};
|
|
291
|
-
const ibData = archive.objects.find(({ class_name }) => class_name
|
|
407
|
+
const ibData = archive.objects.find(({ class_name }) => normalizeClassName(class_name) === "NSIBObjectData");
|
|
292
408
|
const rootId = reference(ibData?.values.NSRoot);
|
|
293
409
|
const hierarchyRoots = rootId === null ? [] : [rootId];
|
|
294
410
|
for (const hierarchyRoot of hierarchyRoots) {
|
|
@@ -296,15 +412,19 @@ const projectNibArchive = (archive) => {
|
|
|
296
412
|
if (root !== null)
|
|
297
413
|
hierarchy.push(root);
|
|
298
414
|
}
|
|
299
|
-
const viewHierarchy = projectNibViewHierarchy(archive.objects, new Set(Object.keys(objects).map(Number)));
|
|
300
|
-
const merged = mergeNibHierarchies(hierarchy, viewHierarchy.hierarchy ?? []);
|
|
415
|
+
const viewHierarchy = projectNibViewHierarchy(archive.objects, new Set(Object.keys(objects).map(Number)), () => budget.tryReserve(128), maxHierarchyNodes);
|
|
416
|
+
const merged = mergeNibHierarchies(hierarchy, viewHierarchy.hierarchy ?? [], () => budget.tryReserve(96), maxHierarchyNodes);
|
|
301
417
|
return {
|
|
302
418
|
omitted: viewHierarchy.omitted + hierarchyOmitted + merged.omitted,
|
|
303
419
|
raw: jsonValueSchema.parse({
|
|
304
420
|
"com.apple.ibtool.document.objects": objects,
|
|
305
421
|
"com.apple.ibtool.document.connections": connections,
|
|
306
422
|
"com.apple.ibtool.document.hierarchy": merged.hierarchy,
|
|
307
|
-
"com.apple.ibtool.document.classes": Object.fromEntries(archive.classes.map((name) =>
|
|
423
|
+
"com.apple.ibtool.document.classes": Object.fromEntries(archive.classes.map((name) => {
|
|
424
|
+
const className = normalizeClassName(name);
|
|
425
|
+
budget.reserveJsonPropertyNameOccurrence(className);
|
|
426
|
+
return [className, {}];
|
|
427
|
+
})),
|
|
308
428
|
}),
|
|
309
429
|
};
|
|
310
430
|
};
|
|
@@ -312,9 +432,9 @@ const isInterfaceBuilderArchive = (path) => {
|
|
|
312
432
|
const lower = path.toLowerCase();
|
|
313
433
|
return lower.endsWith(".nib") || lower.endsWith("/objects.nib");
|
|
314
434
|
};
|
|
315
|
-
const readEntry = async (reader, entry, signal) => {
|
|
316
|
-
if (entry.declaredSize !== null && entry.declaredSize >
|
|
317
|
-
throw new
|
|
435
|
+
const readEntry = async (reader, entry, signal, maxInputBytes = MAX_AGGREGATE_INPUT_BYTES) => {
|
|
436
|
+
if (entry.declaredSize !== null && entry.declaredSize > maxInputBytes)
|
|
437
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "archive exceeds the aggregate Interface Builder decode budget");
|
|
318
438
|
const stream = await reader.open(entry, signal);
|
|
319
439
|
const chunks = [];
|
|
320
440
|
let length = 0;
|
|
@@ -323,18 +443,18 @@ const readEntry = async (reader, entry, signal) => {
|
|
|
323
443
|
? chunk
|
|
324
444
|
: Buffer.from(chunk);
|
|
325
445
|
length += bytes.length;
|
|
326
|
-
if (length >
|
|
446
|
+
if (length > maxInputBytes) {
|
|
327
447
|
stream.destroy();
|
|
328
|
-
throw new
|
|
448
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "archive exceeded the aggregate Interface Builder decode budget");
|
|
329
449
|
}
|
|
330
450
|
chunks.push(bytes);
|
|
331
451
|
}
|
|
332
452
|
return Buffer.concat(chunks, length);
|
|
333
453
|
};
|
|
334
454
|
/** Project decoded plist data and dates while retaining omitted-key coverage. */
|
|
335
|
-
const decodePlist = (bytes) => {
|
|
455
|
+
const decodePlist = (bytes, xmlText) => {
|
|
336
456
|
const { value, omittedPrototypeKeys } = bytes.subarray(0, 8).toString("ascii") === "bplist00"
|
|
337
457
|
? { value: parseBinary(bytes), omittedPrototypeKeys: 0 }
|
|
338
|
-
: parseXmlPropertyList(bytes
|
|
458
|
+
: parseXmlPropertyList(xmlText ?? decodeXmlPlistText(bytes));
|
|
339
459
|
return { value: projectPlistValue(value).value, omittedPrototypeKeys };
|
|
340
460
|
};
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
|
|
2
|
+
/** A named resource-limit failure that keeps budget exhaustion out of decode errors. */
|
|
3
|
+
export class InterfaceBuilderDecodeBudgetExceeded extends Error {
|
|
4
|
+
reason;
|
|
5
|
+
constructor(reason, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.reason = reason;
|
|
8
|
+
this.name = "InterfaceBuilderDecodeBudgetExceeded";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Shared byte budget for decoder records and projected archive data. */
|
|
12
|
+
export class InterfaceBuilderDecodeBudget {
|
|
13
|
+
#initialBytes;
|
|
14
|
+
#remainingBytes;
|
|
15
|
+
constructor(maxBytes) {
|
|
16
|
+
this.#initialBytes = maxBytes;
|
|
17
|
+
this.#remainingBytes = maxBytes;
|
|
18
|
+
}
|
|
19
|
+
/** Representation bytes still available for the current inspection. */
|
|
20
|
+
get remainingBytes() {
|
|
21
|
+
return this.#remainingBytes;
|
|
22
|
+
}
|
|
23
|
+
/** Representation bytes reserved so far. */
|
|
24
|
+
get usedBytes() {
|
|
25
|
+
return this.#initialBytes - this.#remainingBytes;
|
|
26
|
+
}
|
|
27
|
+
/** Reserve representation bytes before allocation, or report exhaustion. */
|
|
28
|
+
reserve(bytes, message) {
|
|
29
|
+
if (!Number.isSafeInteger(bytes) ||
|
|
30
|
+
bytes < 0 ||
|
|
31
|
+
bytes > this.#remainingBytes)
|
|
32
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", message);
|
|
33
|
+
this.#remainingBytes -= bytes;
|
|
34
|
+
}
|
|
35
|
+
/** Reserve an upper bound for one JSON-serialized string occurrence. */
|
|
36
|
+
reserveJsonStringOccurrence(value) {
|
|
37
|
+
// JSON escaping uses at most six ASCII bytes per UTF-16 code unit, plus
|
|
38
|
+
// quotes. Count occurrences even when the source string is shared.
|
|
39
|
+
this.reserve(value.length * 6 + 2, "projected JSON strings exceed the aggregate Interface Builder decode budget");
|
|
40
|
+
}
|
|
41
|
+
/** Reserve the exact JSON string length for a base64 value from Buffer. */
|
|
42
|
+
reserveBase64JsonStringOccurrence(value) {
|
|
43
|
+
// Buffer's base64 alphabet contains no JSON-escaped characters.
|
|
44
|
+
this.reserve(value.length + 2, "projected NIB base64 values exceed the aggregate Interface Builder decode budget");
|
|
45
|
+
}
|
|
46
|
+
/** Reserve an upper bound for one JSON object property name occurrence. */
|
|
47
|
+
reserveJsonPropertyNameOccurrence(value) {
|
|
48
|
+
this.reserve(value.length * 6 + 3, "projected JSON property names exceed the aggregate Interface Builder decode budget");
|
|
49
|
+
}
|
|
50
|
+
/** Reserve bytes for an optional projection without throwing on exhaustion. */
|
|
51
|
+
tryReserve(bytes) {
|
|
52
|
+
if (!Number.isSafeInteger(bytes) ||
|
|
53
|
+
bytes < 0 ||
|
|
54
|
+
bytes > this.#remainingBytes)
|
|
55
|
+
return false;
|
|
56
|
+
this.#remainingBytes -= bytes;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Preflight the representation created by the pinned plist decoder. */
|
|
61
|
+
export const estimatePropertyListDecodeBytes = (bytes, maxBytes, xmlText) => {
|
|
62
|
+
const estimate = bytes.subarray(0, 8).toString("ascii") === "bplist00"
|
|
63
|
+
? estimateBinaryPlistExpansion(bytes, maxBytes)
|
|
64
|
+
: estimateXmlPlistExpansion(bytes, maxBytes, xmlText);
|
|
65
|
+
if (estimate > maxBytes)
|
|
66
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "plist representation exceeds the aggregate Interface Builder decode budget");
|
|
67
|
+
return estimate;
|
|
68
|
+
};
|
|
69
|
+
const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
|
|
70
|
+
const xml = xmlText ?? decodeXmlPlistText(bytes);
|
|
71
|
+
if (/<!DOCTYPE\b[^>]*\[/iu.test(xml))
|
|
72
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "XML plist internal entity expansion exceeds the aggregate Interface Builder decode budget");
|
|
73
|
+
const elementPattern = /<!--[^]*?-->|<!\[CDATA\[[^]*?\]\]>|<!DOCTYPE[^>]*>|<\?[^]*?\?>|<\/?[A-Za-z][^>]*>/giu;
|
|
74
|
+
const decodedSourceBytes = xml.length * 2;
|
|
75
|
+
let elementCount = 0;
|
|
76
|
+
let xmlDepth = 0;
|
|
77
|
+
for (const match of xml.matchAll(elementPattern)) {
|
|
78
|
+
const token = match[0] ?? "";
|
|
79
|
+
if (token.startsWith("<!--") ||
|
|
80
|
+
token.startsWith("<![CDATA[") ||
|
|
81
|
+
token.startsWith("<!DOCTYPE") ||
|
|
82
|
+
token.startsWith("<?"))
|
|
83
|
+
continue;
|
|
84
|
+
elementCount += 1;
|
|
85
|
+
if (token.startsWith("</"))
|
|
86
|
+
xmlDepth -= 1;
|
|
87
|
+
else if (!token.endsWith("/>")) {
|
|
88
|
+
xmlDepth += 1;
|
|
89
|
+
if (xmlDepth > 128)
|
|
90
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "XML plist nesting exceeds the aggregate Interface Builder decode budget");
|
|
91
|
+
}
|
|
92
|
+
if (decodedSourceBytes * 2 + elementCount * 128 > maxBytes)
|
|
93
|
+
return maxBytes + 1;
|
|
94
|
+
}
|
|
95
|
+
return decodedSourceBytes * 2 + elementCount * 128;
|
|
96
|
+
};
|
|
97
|
+
/** Count every expanded binary-plist reference before calling plist.parseBinary. */
|
|
98
|
+
const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
|
|
99
|
+
if (bytes.length < 40)
|
|
100
|
+
throw new TypeError("binary plist trailer is truncated");
|
|
101
|
+
const trailer = bytes.length - 32;
|
|
102
|
+
const offsetSize = bytes[trailer + 6] ?? 0;
|
|
103
|
+
const referenceSize = bytes[trailer + 7] ?? 0;
|
|
104
|
+
if (![1, 2, 4, 8].includes(offsetSize) ||
|
|
105
|
+
![1, 2, 4, 8].includes(referenceSize))
|
|
106
|
+
throw new TypeError("binary plist trailer integer sizes are invalid");
|
|
107
|
+
const readInteger = (offset, size) => {
|
|
108
|
+
if (offset < 0 || size < 1 || offset + size > bytes.length)
|
|
109
|
+
return -1;
|
|
110
|
+
let value = 0;
|
|
111
|
+
for (let index = 0; index < size; index += 1)
|
|
112
|
+
value = value * 256 + (bytes[offset + index] ?? 0);
|
|
113
|
+
return Number.isSafeInteger(value) ? value : -1;
|
|
114
|
+
};
|
|
115
|
+
const objectCount = readInteger(trailer + 8, 8);
|
|
116
|
+
const topObject = readInteger(trailer + 16, 8);
|
|
117
|
+
const offsetTable = readInteger(trailer + 24, 8);
|
|
118
|
+
if (objectCount < 1 ||
|
|
119
|
+
topObject < 0 ||
|
|
120
|
+
topObject >= objectCount ||
|
|
121
|
+
offsetTable < 8 ||
|
|
122
|
+
offsetTable + objectCount * offsetSize > trailer)
|
|
123
|
+
throw new TypeError("binary plist trailer or object table is invalid");
|
|
124
|
+
let estimate = bytes.length * 2 + objectCount * 16;
|
|
125
|
+
if (estimate > maxBytes)
|
|
126
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist object table exceeds the aggregate Interface Builder decode budget");
|
|
127
|
+
const active = new Set();
|
|
128
|
+
const pending = [
|
|
129
|
+
{ object: topObject, depth: 0, exit: false },
|
|
130
|
+
];
|
|
131
|
+
let pendingObjectCount = 1;
|
|
132
|
+
while (pending.length > 0) {
|
|
133
|
+
const entry = pending.pop();
|
|
134
|
+
if (entry === undefined)
|
|
135
|
+
break;
|
|
136
|
+
if (entry.exit) {
|
|
137
|
+
active.delete(entry.object);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
pendingObjectCount -= 1;
|
|
141
|
+
if (entry.depth > 128)
|
|
142
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist nesting exceeds the aggregate Interface Builder decode budget");
|
|
143
|
+
if (active.has(entry.object))
|
|
144
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference cycle exceeds the aggregate Interface Builder decode budget");
|
|
145
|
+
estimate += 96;
|
|
146
|
+
if (estimate > maxBytes)
|
|
147
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
|
|
148
|
+
const offset = readInteger(offsetTable + entry.object * offsetSize, offsetSize);
|
|
149
|
+
if (offset < 8 || offset >= offsetTable)
|
|
150
|
+
throw new TypeError("binary plist object offset is invalid");
|
|
151
|
+
const marker = bytes[offset] ?? 0;
|
|
152
|
+
const type = marker >> 4;
|
|
153
|
+
let size = marker & 0x0f;
|
|
154
|
+
let cursor = offset + 1;
|
|
155
|
+
if (size === 0x0f && type !== 0 && type !== 8) {
|
|
156
|
+
const extMarker = bytes[cursor] ?? 0;
|
|
157
|
+
if (extMarker >> 4 !== 1 || (extMarker & 0x0f) > 3)
|
|
158
|
+
throw new TypeError("binary plist extended object size is invalid");
|
|
159
|
+
cursor += 1;
|
|
160
|
+
const integerSize = 1 << (extMarker & 0x0f);
|
|
161
|
+
size = readInteger(cursor, integerSize);
|
|
162
|
+
cursor += integerSize;
|
|
163
|
+
if (size < 0 || cursor > offsetTable)
|
|
164
|
+
throw new TypeError("binary plist extended object size is invalid");
|
|
165
|
+
}
|
|
166
|
+
if (type === 4 || type === 5 || type === 6) {
|
|
167
|
+
const byteLength = type === 6 ? size * 2 : size;
|
|
168
|
+
if (cursor + byteLength > offsetTable)
|
|
169
|
+
throw new TypeError("binary plist scalar object is truncated");
|
|
170
|
+
estimate += type === 4 ? size + 4 * Math.ceil(size / 3) : byteLength * 2;
|
|
171
|
+
if (estimate > maxBytes)
|
|
172
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist scalar expansion exceeds the aggregate Interface Builder decode budget");
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (type !== 10 && type !== 13)
|
|
176
|
+
continue;
|
|
177
|
+
const childCount = type === 13 ? size * 2 : size;
|
|
178
|
+
const refsEnd = cursor + childCount * referenceSize;
|
|
179
|
+
if (!Number.isSafeInteger(refsEnd) || refsEnd > offsetTable)
|
|
180
|
+
throw new TypeError("binary plist reference table is truncated");
|
|
181
|
+
const availableNodes = Math.floor((maxBytes - estimate) / 96);
|
|
182
|
+
if (childCount > availableNodes - pendingObjectCount)
|
|
183
|
+
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
|
|
184
|
+
active.add(entry.object);
|
|
185
|
+
pending.push({ object: entry.object, depth: entry.depth, exit: true });
|
|
186
|
+
for (let index = childCount - 1; index >= 0; index -= 1) {
|
|
187
|
+
const reference = readInteger(cursor + index * referenceSize, referenceSize);
|
|
188
|
+
if (reference < 0 || reference >= objectCount)
|
|
189
|
+
throw new TypeError("binary plist reference is invalid");
|
|
190
|
+
pending.push({ object: reference, depth: entry.depth + 1, exit: false });
|
|
191
|
+
}
|
|
192
|
+
pendingObjectCount += childCount;
|
|
193
|
+
}
|
|
194
|
+
return estimate;
|
|
195
|
+
};
|