Skip to content

Concolic for TypeScript#341

Draft
CaelmBleidd wants to merge 6 commits into
mainfrom
caelmbleidd/ts_pbt
Draft

Concolic for TypeScript#341
CaelmBleidd wants to merge 6 commits into
mainfrom
caelmbleidd/ts_pbt

Conversation

@CaelmBleidd

Copy link
Copy Markdown
Member

No description provided.

Prepare usvm-ts for hybrid (concrete + symbolic) analysis:
- add TsInputTypeHints / TsHintType and TsOptions.inputTypeHints: observed-type
  profiles from a dynamic phase restrict fake-object type discriminators for
  parameters with unresolved types in getInitialState (an unsound prune with an
  orchestrator-level hint-free fallback; default EMPTY keeps behavior unchanged)
- add TsTestResolver.resolveInputs to resolve the input valuation of states
  that have not terminated yet (e.g. captured at target propagation time)
- move TsTestResolver and ObjectClass from test to main sources so that
  external drivers can extract concrete inputs from symbolic states
A research prototype combining dynamic and static analysis of TS at the
EtsIR level:

- the first concrete EtsIR interpreter (full ECMAScript coercion semantics,
  calls/objects/arrays/intrinsics; anything unmodeled is reported as
  Unsupported, never a silently wrong value)
- PBT phase: type-driven input generators biased by constants mined from the
  method body, online statement + branch-edge coverage, failure deduplication
  and greedy shrinking, runtime type profiling
- symbolic phase: for every branch edge left uncovered by PBT, a
  TsReachabilityTarget chain is built and TsMachine runs in TARGETED mode
  (one machine run per target); the reaching state is captured at target
  propagation time, its inputs are extracted from the SMT model and replayed
  on the concrete interpreter to confirm the edge
- observed-type hints from the PBT phase feed TsOptions.inputTypeHints,
  pruning fake-object discriminators, with an automatic hint-free fallback
- HybridAnalyzer orchestrator with 4 ablation modes (PBT_ONLY, SYMBOLIC_ONLY,
  HYBRID, HYBRID_WITH_HINTS), JSON reports and a CLI for batch experiments
- test suite: JS semantics unit tests, DSL-built IR interpreter tests, a
  differential oracle replaying TsMachine-produced inputs concretely, PBT
  phase tests, end-to-end hybrid tests and a hints ablation harness
ArkAnalyzer/EtsIR pipeline overview, concrete interpreter design and
differential-testing findings (AA if-successor order drift, engine `+`
approximation on references, targeted-mode stop/collect race), and the
hybrid pipeline description with first corpus numbers.
@CaelmBleidd CaelmBleidd marked this pull request as draft July 5, 2026 21:05
@CaelmBleidd CaelmBleidd requested a review from Copilot July 5, 2026 21:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a hybrid analysis pipeline for TypeScript/ArkTS combining a concrete EtsIR interpreter (for PBT + coverage + type profiling) with targeted symbolic execution, plus an “observed input type hints” mechanism to prune fake-object discriminator search during symbolic initialization.

Changes:

  • Add usvm-ts-pbt module implementing a concrete EtsIR interpreter, PBT phase, hybrid orchestrator, reporting CLI, and a dedicated test suite.
  • Extend usvm-ts with TsInputTypeHints/TsOptions.inputTypeHints and interpreter-side hint application for unresolved parameters.
  • Add TsTestResolver.resolveInputs to extract input valuations from non-terminated states (for target-reaching state capture + replay).

Reviewed changes

Copilot reviewed 35 out of 37 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
usvm-ts/src/main/kotlin/org/usvm/util/TsTestResolver.kt Add input-only model resolution for mid-execution states.
usvm-ts/src/main/kotlin/org/usvm/util/ObjectClass.kt Add helper to synthesize an Object class for resolution.
usvm-ts/src/main/kotlin/org/usvm/machine/TsOptions.kt Add inputTypeHints option plumbing with default EMPTY.
usvm-ts/src/main/kotlin/org/usvm/machine/TsInputTypeHints.kt Define hint types and method/parameter-index keyed hint map.
usvm-ts/src/main/kotlin/org/usvm/machine/interpreter/TsInterpreter.kt Apply observed-type hints to constrain fake-object discriminators.
usvm-ts-pbt/src/test/resources/pbt/HybridSamples.ts Add fixtures for hybrid/PBT/hints end-to-end scenarios.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/util/Resources.kt Add resource path/stream helpers for tests.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/util/LoadEts.kt Add EtsIR loading helpers for resources and filesystem.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/interpreter/JsSemanticsTest.kt Unit tests for concrete JS coercion/ops semantics.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/interpreter/ConcreteVsSymbolicDifferentialTest.kt Differential oracle: symbolic model replay vs concrete interpreter.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/interpreter/ConcreteInterpreterDslTest.kt Interpreter tests over DSL-built EtsIR (no ArkAnalyzer).
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/hybrid/PbtPhaseTest.kt Tests for PBT coverage, shrinking, profiling, determinism.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/hybrid/HybridE2eTest.kt End-to-end hybrid pipeline + hints ablation harness.
usvm-ts-pbt/src/test/kotlin/org/usvm/ts/pbt/hybrid/HybridAnalyzerTest.kt Analyzer modes + report JSON round-trip tests.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/report/Main.kt CLI entrypoint for batch hybrid experiments and JSON output.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/report/HybridReport.kt Serializable report schema for experiments and tooling.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/report/Conversions.kt Convert between symbolic TsTestValue and concrete VValue.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/VValue.kt Define concrete runtime value universe for interpreter.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/JsSemantics.kt Implement concrete JS semantics (coercions, ops, typeof, in).
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/Intrinsics.kt Model built-in namespaces and selected methods/fields.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/ExecutionResult.kt Define execution outcomes + internal control-flow signals.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/ExecutionListener.kt Listener hooks for coverage/profiling and composition.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/EtsConcreteInterpreter.kt Implement CFG-walking concrete interpreter over EtsIR.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/interpreter/CallResolver.kt Concrete name-based dispatch over scene hierarchy.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/hybrid/TypeProfiler.kt Record runtime input type tags and export to hints.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/hybrid/SymbolicPhase.kt Target uncovered edges, capture reaching state, resolve inputs, replay/merge coverage.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/hybrid/PbtPhase.kt PBT loop with generator, shrinker, coverage and profiling.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/hybrid/HybridAnalyzer.kt Orchestrate phases across modes; emit report model.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/gen/Shrinker.kt Greedy shrinker for failure minimization.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/gen/Generators.kt Type-driven random input generation with mined constants.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/gen/ConstantMiner.kt Mine numeric/string literals from method bodies to bias generators.
usvm-ts-pbt/src/main/kotlin/org/usvm/ts/pbt/coverage/CoverageTracker.kt Statement + branch-edge coverage and trace merge support.
usvm-ts-pbt/build.gradle.kts Add new module build config + runHybrid CLI task.
settings.gradle.kts Register usvm-ts-pbt Gradle module.
docs/ts-pbt/03-hybrid-pipeline.md Document implemented hybrid pipeline and findings.
docs/ts-pbt/02-concrete-interpreter-and-differential-findings.md Document concrete interpreter + differential findings.
docs/ts-pbt/01-arkanalyzer-and-ets-ir.md Document ArkAnalyzer/EtsIR wiring and methodology notes.
Comments suppressed due to low confidence (1)

usvm-ts/src/main/kotlin/org/usvm/util/TsTestResolver.kt:100

  • resolveInputs assumes state.models is non-empty (state.models.first()), but UState.models is explicitly allowed to be empty (e.g. when forking without a solver). For mid-execution states this will throw NoSuchElementException and makes the new API fragile. Compute a model from the current pathConstraints when missing (and optionally cache it back into state.models) so input resolution works regardless of solver-for-forks configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +429 to +433
is VArray -> if (lhv.field.name == "length") {
val n = JsSemantics.toNumber(value).toInt()
while (target.elements.size > n) target.elements.removeAt(target.elements.size - 1)
while (target.elements.size < n) target.elements.add(VUndefined)
}
Comment on lines +3 to +8
import mu.KotlinLogging
import java.io.InputStream
import java.nio.file.Path
import kotlin.io.path.toPath

private val logger = KotlinLogging.logger {}
The engine resolves relational operators on mixed-type fake-object operands
per sort pair (Lt.onBool = !lhs && rhs) instead of the JS ToNumber coercion,
so e.g. `false < 0.0` is reported true while JS gives `0 < 0 === false`.
The divergence surfaces nondeterministically depending on which input models
the machine samples, making the suite flaky without the whitelist entry.
- register usvm-ts-pbt in validateProjectList (the lint job failure)
- pin @types/node@22 when building ArkAnalyzer in ci-ts: a transitively
  hoisted @types/node >= 24 uses TypeScript syntax the AA toolchain cannot
  parse; both --no-save packages (ohos-typescript is installed --no-save by
  the AA postinstall script) must go in a single npm install invocation,
  because every npm install re-resolves the tree and drops previous
  --no-save additions
- run :usvm-ts-pbt:check in the ci-ts job
- add detekt baselines for the new module
- follow the frontends' compare-to-zero truthiness idiom in the concrete
  interpreter: both ArkAnalyzer and the jacodb ts-frontend lower `if (x)` to
  `x != 0`, which differs from JS loose (in)equality for non-number operands
  ([] != 0 is false in JS, yet [] is truthy); compare-to-zero on a non-number
  now means ToBoolean
- whitelist two more confirmed engine divergences found by running the
  differential oracle under the second frontend: the NaN hole of the same
  idiom (undefined treated as truthy via ToNumber(undefined) != 0) and the
  doubly-ambiguous transitiveCoercionNoTypes
- add an opt-in composite-build switch (-PuseLocalJacodb[=<path>]) for
  substituting a locally built jacodb
- document the compatibility check (docs/ts-pbt/04)

Full usvm-ts-pbt suite is green under both EtsIR providers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants