[PR #7192] feat(unicorn): add function-level emulation provider (Phase 1) #7708

Open
opened 2026-11-03 13:39:48 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7192
Author: @reynold-hu
Created: 10/26/2026
Status: 🔄 Open

Base: main ← Head: unicorn-emulation-phase1


📝 Commits (7)

  • acdab66 feat(unicorn): add function-level emulation provider (Phase 1)
  • 79651c8 Merge remote-tracking branch 'origin/main' into unicorn-emulation-phase1
  • f1dbc16 fix(unicorn): address Greptile review findings and CI failures
  • 111a0ad test(unicorn): cover Greptile fixes and CI failures
  • 7f065b8 test(unicorn): fix provider identity import path
  • bc28d68 fix(unicorn): match main's ProviderAvailability shape
  • 9ead8d5 test(unicorn): keep provider identity local to the contract test

📊 Changes

47 files changed (+4125 additions, -27 deletions)

View changed files

➕ bridge/unicorn/emulate_function.py (+39 -0)
➕ bridge/unicorn/emulate_function_impl.py (+713 -0)
➕ bridge/unicorn/test_emulate_function_impl.py (+264 -0)
📝 package.json (+3 -0)
📝 scripts/lib/test-projects.mjs (+1 -1)
➕ scripts/verify-unicorn.mjs (+151 -0)
📝 src/android/JadxDoctor.ts (+4 -2)
📝 src/application/AnalysisContextQueries.test.ts (+1 -1)
📝 src/application/AnalysisProvider.ts (+16 -0)
📝 src/application/binary/BinarySessionOpen.ts (+1 -1)
📝 src/application/native/NativeFunctionMatchingService.ts (+4 -2)
📝 src/browser/history/NodeCaptureAdapter.ts (+1 -1)
📝 src/composition/auxiliaryAnalysisProviders.ts (+14 -1)
📝 src/composition/capabilityDeclarations.ts (+8 -0)
📝 src/contracts/toolContracts.ts (+2 -0)
📝 src/contracts/toolEffects.test.ts (+2 -0)
📝 src/contracts/toolEffects.ts (+3 -0)
📝 src/contracts/toolFamilies.ts (+3 -0)
➕ src/contracts/unicorn/unicornToolContracts.test.ts (+150 -0)
➕ src/contracts/unicorn/unicornToolContracts.ts (+205 -0)

...and 27 more files

📄 Description

Draft PR for #7142 — opened so the scope decision can be made against actual code, as suggested in the issue thread.

What this does

Adds a single operation, emulate_function, that runs one x86_64 function in isolation under a declared harness:

  • Declared inputs: initial register values, an initial memory image (address → bytes), and stack setup. Nothing is read from the host process or filesystem at run time.
  • Imports/syscalls are stubbed and recorded, never executed on the host.
  • Budgets (instruction cap, wall-time, address space) with explicit stop reasons: returned, unmapped_access, unsupported_instruction, stubbed_call, instruction_budget_exhausted, timeout, escaped_code_region.
  • Results are returned as Evidence (authority controlled-replay, isolation process via an owned bridge subprocess, confidence observed for effects actually produced).
  • Engine: Unicorn 2.1.2 through the already-pinned pwntools Python bridge profile (REA_PWNTOOLS_PYTHON). No new npm dependency, no new config variable, no in-process native binding.

Review questions from #7142, answered

  1. Default stub policy for undeclared imports/syscalls: return 0 and record the call (log-and-continue), stated in the result. A caller-declared return value overrides the default when provided.
  2. Initial memory image sourcing: Phase 1 takes an explicit caller-provided map only. Exporting segments from an existing provider (Ghidra segments / Frida dump) is a later option, not in this PR.

Tests

  • Unit: 48/48
  • Boundary: 8/8
  • Acceptance: 3/3
  • Real-engine verification (scripts/verify-unicorn.mjs): 9/9
  • Full check:pr gate: not run yet — will run before this leaves draft.

Limits (Phase 1)

  • x86_64 only; Linux-x64 host gate inherited from the pwntools lane.
  • No OS modeled: no real syscalls, threading, signals, filesystem, or network. Anything beyond declared memory and stubs is reported as unobserved, not assumed.
  • No self-modifying or JIT-emitted code; code outside the declared function bytes stops the run with an explicit reason.
  • A finite run establishes observed behavior for the declared inputs only — it is not a proof of equivalence and is never reported as one.

This is a draft for scope discussion. Per CONTRIBUTING's fail-closed rule, integration is not assumed: the scope decision on #7142 still stands as the gate.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/7192 **Author:** [@reynold-hu](https://github.com/reynold-hu) **Created:** 10/26/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `unicorn-emulation-phase1` --- ### 📝 Commits (7) - [`acdab66`](https://github.com/morluto/rea/commit/acdab66f447668ec0a2b68a2575002aa660a1be2) feat(unicorn): add function-level emulation provider (Phase 1) - [`79651c8`](https://github.com/morluto/rea/commit/79651c8a3f905c65e81cf1236af786907bd58081) Merge remote-tracking branch 'origin/main' into unicorn-emulation-phase1 - [`f1dbc16`](https://github.com/morluto/rea/commit/f1dbc16f19a30f422f2041c9fe308b0b32b88532) fix(unicorn): address Greptile review findings and CI failures - [`111a0ad`](https://github.com/morluto/rea/commit/111a0addc66cc4dfc16533871966d805f2815f15) test(unicorn): cover Greptile fixes and CI failures - [`7f065b8`](https://github.com/morluto/rea/commit/7f065b866080c4787b0a84c46cdeca559c8d30eb) test(unicorn): fix provider identity import path - [`bc28d68`](https://github.com/morluto/rea/commit/bc28d68e3cf1ed3b266e61f201dd2c21e79fa94f) fix(unicorn): match main's ProviderAvailability shape - [`9ead8d5`](https://github.com/morluto/rea/commit/9ead8d5f698dc3ccb7fd04019e2de82616c29272) test(unicorn): keep provider identity local to the contract test ### 📊 Changes **47 files changed** (+4125 additions, -27 deletions) <details> <summary>View changed files</summary> ➕ `bridge/unicorn/emulate_function.py` (+39 -0) ➕ `bridge/unicorn/emulate_function_impl.py` (+713 -0) ➕ `bridge/unicorn/test_emulate_function_impl.py` (+264 -0) 📝 `package.json` (+3 -0) 📝 `scripts/lib/test-projects.mjs` (+1 -1) ➕ `scripts/verify-unicorn.mjs` (+151 -0) 📝 `src/android/JadxDoctor.ts` (+4 -2) 📝 `src/application/AnalysisContextQueries.test.ts` (+1 -1) 📝 `src/application/AnalysisProvider.ts` (+16 -0) 📝 `src/application/binary/BinarySessionOpen.ts` (+1 -1) 📝 `src/application/native/NativeFunctionMatchingService.ts` (+4 -2) 📝 `src/browser/history/NodeCaptureAdapter.ts` (+1 -1) 📝 `src/composition/auxiliaryAnalysisProviders.ts` (+14 -1) 📝 `src/composition/capabilityDeclarations.ts` (+8 -0) 📝 `src/contracts/toolContracts.ts` (+2 -0) 📝 `src/contracts/toolEffects.test.ts` (+2 -0) 📝 `src/contracts/toolEffects.ts` (+3 -0) 📝 `src/contracts/toolFamilies.ts` (+3 -0) ➕ `src/contracts/unicorn/unicornToolContracts.test.ts` (+150 -0) ➕ `src/contracts/unicorn/unicornToolContracts.ts` (+205 -0) _...and 27 more files_ </details> ### 📄 Description Draft PR for #7142 — opened so the scope decision can be made against actual code, as suggested in the issue thread. ## What this does Adds a single operation, `emulate_function`, that runs one x86_64 function in isolation under a declared harness: - Declared inputs: initial register values, an initial memory image (address → bytes), and stack setup. Nothing is read from the host process or filesystem at run time. - Imports/syscalls are stubbed and recorded, never executed on the host. - Budgets (instruction cap, wall-time, address space) with explicit stop reasons: returned, unmapped_access, unsupported_instruction, stubbed_call, instruction_budget_exhausted, timeout, escaped_code_region. - Results are returned as Evidence (authority `controlled-replay`, isolation `process` via an owned bridge subprocess, confidence `observed` for effects actually produced). - Engine: Unicorn 2.1.2 through the already-pinned pwntools Python bridge profile (`REA_PWNTOOLS_PYTHON`). No new npm dependency, no new config variable, no in-process native binding. ## Review questions from #7142, answered 1. **Default stub policy for undeclared imports/syscalls**: return 0 and record the call (log-and-continue), stated in the result. A caller-declared return value overrides the default when provided. 2. **Initial memory image sourcing**: Phase 1 takes an explicit caller-provided map only. Exporting segments from an existing provider (Ghidra segments / Frida dump) is a later option, not in this PR. ## Tests - Unit: 48/48 - Boundary: 8/8 - Acceptance: 3/3 - Real-engine verification (`scripts/verify-unicorn.mjs`): 9/9 - Full `check:pr` gate: not run yet — will run before this leaves draft. ## Limits (Phase 1) - x86_64 only; Linux-x64 host gate inherited from the pwntools lane. - No OS modeled: no real syscalls, threading, signals, filesystem, or network. Anything beyond declared memory and stubs is reported as unobserved, not assumed. - No self-modifying or JIT-emitted code; code outside the declared function bytes stops the run with an explicit reason. - A finite run establishes observed behavior for the declared inputs only — it is not a proof of equivalence and is never reported as one. This is a draft for scope discussion. Per CONTRIBUTING's fail-closed rule, integration is not assumed: the scope decision on #7142 still stands as the gate. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7708
No description provided.