module NoirMobileLinker

Overview

Post-analysis pass that links mobile deep-link endpoints (produced by the config-file analyzers from AndroidManifest.xml) to the source code that handles them. For each Android mobile endpoint it:

  1. resolves the handling component (metadata["via"] / the intent:// component) to its .kt/.java source file,
  2. adds that file as a code_path so the AI-context builder scans the handler body for sinks/guards, and
  3. extracts the handler's 1-hop callees into endpoint.callees.

The existing AIContext builder then derives sinks/guards/sources from the handler snippet and callees — no mobile-specific wiring needed there. iOS endpoints have no per-endpoint via, so the linker discovers central App/SceneDelegate/SwiftUI handlers and attaches them by deep-link kind.

Defined in:

mobile/linker.cr

Constant Summary

BUNDLE_PARAM_RE = /\b(?:arguments|requireArguments\(\)|getArguments\(\)|savedStateHandle|extras|intent\.extras|intent\.getExtras\(\))\??\s*\.\s*get(?:String|Int|Integer|Boolean|Long|Float|Double|Char|Byte|Short|Parcelable|Serializable|StringArray|CharSequence|Bundle)?(?:\s*<[^>]+>)?\s*\(\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z_][A-Za-z0-9_.]*))/
EXTRA_PARAM_RE = /\.(?:get\w*Extra|hasExtra)\s*\(\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z_][A-Za-z0-9_.]*))/
HANDLER_METHODS = ["onCreate", "onNewIntent", "onStart", "onResume", "onStartCommand", "onHandleIntent", "handleIntent", "handleDeepLink", "onReceive", "onBind", "onCreateView", "onViewCreated"] of ::String

Methods where an Android component reads its inbound intent / deep link. onCreateView / onViewCreated cover Jetpack Navigation fragment destinations, which receive deep-link path/query values as arguments.

PROVIDER_HANDLER_METHODS = ["onCreate", "query", "insert", "update", "delete", "bulkInsert", "openFile", "openAssetFile", "call", "getType", "applyBatch"] of ::String

ContentProvider entry points. A provider is reached via ContentResolver, so its inbound data (the uri, selection, selectionArgs, projection) arrives through these methods rather than an Intent — query / openFile are the classic SQL-injection / path-traversal sinks. Kept separate from HANDLER_METHODS so these generic verbs are only scanned for provider components, not grafted onto every activity that happens to have an update().

QUERY_PARAM_RE = /\.getQueryParameter\s*\(\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z_][A-Za-z0-9_.]*))/

Inputs the handler reads from the inbound deep link. getQueryParameter reads a real URI query parameter (surfaced as a "query" param, baked into the URL like any other); the get*Extra family reads Intent extras (a Bundle, not part of the URI) and is surfaced as the "extra" type.

Class Method Summary

Class Method Detail

def self.apply(endpoints : Array(Endpoint), logger : NoirLogger) : Array(Endpoint) #

[View source]
def self.read_content(path : String) : String | Nil #

Content cache may be cold (budget exhausted, or caching disabled in tests); fall back to a direct read per the CodeLocator contract.


[View source]