-
Notifications
You must be signed in to change notification settings - Fork 8
feat(adapter)!: exact compatibility registry, verified adapter store, and contained descriptor execution #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eb35509
6b6e9a2
161dc9b
6d4d7bf
aa85690
cacb100
ea4a646
177404a
3a089a2
b4d39c6
f4a3e47
86a4930
41c5b84
fb554dd
4cfa842
bf9f8c0
d4610af
38ec90f
f3d369e
56805d7
c4f7bf3
9b7fc17
4642d3d
d285418
c35412f
5cc344d
ff11582
070b08b
a50b42d
ae10541
ac57d18
37168da
4910a01
647aad6
53cdcd7
7518429
3fbdb0e
48132ad
01ad4c8
c670636
dd48988
25e1668
480917c
2e2eb60
effc60e
e227ecf
e89be70
e465049
fb6e000
746adfe
2351ef3
ae5eaa2
d25938b
32e7173
60c5d44
6cf894f
d3f2a82
a760671
a4125d0
91d84b3
f108a87
c84eb32
8b001c6
98b5330
931c39c
aebab76
bcdde1e
2f9fe21
7c7dbec
9eb565b
b31a97d
3258445
0398be4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,5 @@ | |
| /out | ||
| /.venv | ||
| *.log | ||
| /adapters/installed/* | ||
| !/adapters/installed/.gitkeep | ||
| __pycache__/ | ||
| *.pyc | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,21 +81,28 @@ nix profile upgrade flutterdec | |
|
|
||
| Current prerelease: [`v0.1.0-alpha.4`](https://github.com/caverav/flutterdec/releases/tag/v0.1.0-alpha.4) | ||
|
|
||
| The archive is a prefix, not a lone binary: it holds `bin/flutterdec` plus the compatibility | ||
| registry, the runtime profiles and the packaged producer under `share/flutterdec`. The CLI finds | ||
| that data relative to its own executable, so copy `bin` and `share` to the same prefix and keep | ||
| them together. A binary moved out on its own reports which directories it looked in and stops. | ||
|
|
||
| Linux x64: | ||
|
|
||
| ```bash | ||
| curl -fLO https://github.com/caverav/flutterdec/releases/download/v0.1.0-alpha.4/flutterdec-v0.1.0-alpha.4-Linux-X64.tar.gz | ||
| tar -xzf flutterdec-v0.1.0-alpha.4-Linux-X64.tar.gz | ||
| sudo install -m 0755 flutterdec /usr/local/bin/flutterdec | ||
| mkdir -p flutterdec-v0.1.0-alpha.4 | ||
| tar -xzf flutterdec-v0.1.0-alpha.4-Linux-X64.tar.gz -C flutterdec-v0.1.0-alpha.4 | ||
| sudo cp -R flutterdec-v0.1.0-alpha.4/bin flutterdec-v0.1.0-alpha.4/share /usr/local/ | ||
| flutterdec --help | ||
| ``` | ||
|
|
||
| macOS arm64: | ||
|
|
||
| ```bash | ||
| curl -fLO https://github.com/caverav/flutterdec/releases/download/v0.1.0-alpha.4/flutterdec-v0.1.0-alpha.4-macOS-ARM64.tar.gz | ||
| tar -xzf flutterdec-v0.1.0-alpha.4-macOS-ARM64.tar.gz | ||
| sudo install -m 0755 flutterdec /usr/local/bin/flutterdec | ||
| mkdir -p flutterdec-v0.1.0-alpha.4 | ||
| tar -xzf flutterdec-v0.1.0-alpha.4-macOS-ARM64.tar.gz -C flutterdec-v0.1.0-alpha.4 | ||
| sudo cp -R flutterdec-v0.1.0-alpha.4/bin flutterdec-v0.1.0-alpha.4/share /usr/local/ | ||
| flutterdec --help | ||
| ``` | ||
|
|
||
|
|
@@ -137,13 +144,36 @@ If this is your first run, this is the shortest useful path. | |
| flutterdec info ./sample.apk --json | ||
| ``` | ||
|
|
||
| `info` resolves the Dart SDK version straight from the snapshot hash, with no adapter | ||
| installed and no disassembly: | ||
| `info` reads the snapshot identity out of the header with no adapter installed and no | ||
| disassembly: `snapshot_hash`, `arch`, `snapshot_features`, `compressed_pointers`, and | ||
| `registry_record_present`. | ||
|
|
||
| The Dart profile fields come from the host registry record that the identity matched, | ||
| and appear only once that record's adapter is installed, because the profile is | ||
| SHA-256 verified as part of authorizing the run: | ||
|
|
||
| - `dart_version` (for example `3.9.2`) | ||
| - `dart_aliases`: zero or more SDK labels, each with its own `ecosystem`, `version`, | ||
| and `provenance`. They are provenance only and never select a parser or a profile. | ||
| - `dart_version`: a display value, never an exact SDK claim. It is `unverified` when | ||
| the record carries aliases and `unavailable` when it carries none. | ||
| - `dart_tag_style` (`CID_INT32`, `CID_SHIFT1`, or `OBJECT_HEADER`) | ||
|
|
||
| Both are `null` for snapshot hashes not in the bundled table (`data/dart-profiles.json`). | ||
| ```json | ||
| "dart_aliases": [ | ||
| {"ecosystem": "dart", "version": "3.5.0", "provenance": "r2flutter-offsets"}, | ||
| {"ecosystem": "flutter", "version": "3.24.0", "provenance": "sample-build-metadata"} | ||
| ], | ||
| "dart_version": "unverified", | ||
| "dart_tag_style": "OBJECT_HEADER" | ||
| ``` | ||
|
|
||
| All three are `null` when no registry record matches the snapshot identity, and when a | ||
| matching record's adapter is not installed. | ||
|
|
||
| The registry record is the only authority for SDK labels, so a snapshot with no record | ||
| reports no alias at all — including hashes that an earlier version labelled from the | ||
| bundled profile table. That is the accepted cost of keeping one authority: there is no | ||
| second, weaker path that names a version from a hash. | ||
|
|
||
| For APK inputs, `info` reports Android startup summary fields such as: | ||
|
|
||
|
|
@@ -161,6 +191,10 @@ If adapter metadata is available, `info` also reports package and compatibility | |
| - `identity_rejection` (why no adapter could be selected, when none could) | ||
| - `model_capabilities` | ||
| - `compatibility_warnings` | ||
| - `provider` (one block: requested and resolved backend, whether an adapter was | ||
| executed at all and why not, host and target architectures, the producer and | ||
| its artifact digest, the parser family, profile and artifact the registry | ||
| named, and the containment the child reported) | ||
|
|
||
| 2. Install the adapter for the detected Dart hash: | ||
|
|
||
|
|
@@ -216,6 +250,14 @@ flutterdec adapter install --dart-hash <HASH> | |
| flutterdec adapter list | ||
| ``` | ||
|
|
||
| Adapters install into a writable store outside any checkout: `FLUTTERDEC_ADAPTER_STORE` when set, | ||
| otherwise `$XDG_DATA_HOME/flutterdec/adapters` or `$HOME/.local/share/flutterdec/adapters`. The | ||
| compatibility registry and the runtime profiles are read-only package data, found next to the binary at | ||
| `share/flutterdec` (or wherever `FLUTTERDEC_DATA_DIR` points). Neither location depends on your current | ||
| directory, so a release binary behaves the same everywhere. `adapter list` reports `verified`, | ||
| `missing`, `corrupt`, `incompatible`, or `unavailable` per record and exits 2 if the store holds an | ||
| install it cannot back. See [docs/user-guide.md](docs/user-guide.md) for the full rules. | ||
|
|
||
| Decompile with the default app-focused scope: | ||
|
|
||
| ```bash | ||
|
|
@@ -358,16 +400,26 @@ flutterdec decompile ./sample.apk -o ./out --analysis-profile light | |
|
|
||
| Adapter backend selection: | ||
|
|
||
| - `--adapter-backend auto` (default): try r2flutter, then Blutter, then fall back to the internal adapter | ||
| - `--adapter-backend internal`: force the internal adapter only | ||
| - `--adapter-backend auto` (default): try r2flutter, then Blutter, then the producer's internal path | ||
| - `--adapter-backend internal`: recover in core; select nothing, read no registry, execute nothing | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Reconcile the Line 404 states that If 📝 Proposed documentation fix | Backend | Function names | Classes | ObjectPool |
| --- | --- | --- | --- |
| core recovery | none at all; code ranges are unnamed | none | unavailable |
-| `internal` | none at all; code ranges are unnamed | none | carved strings, ordinal index space |
| `blutter` | scraped from Blutter's rendered source, heuristic | yes | Blutter `pp.txt` entries, ordinal index space |Also applies to: 422-422 🤖 Prompt for AI Agents |
||
| - `--adapter-backend blutter`: require the Blutter backend and fail if unavailable | ||
| - `--adapter-backend r2-flutter`: require the r2flutter backend and fail if unavailable | ||
| - `--adapter-timeout <SECONDS>`: bound one adapter invocation | ||
| - `--require-snapshot-hash-match`: fail unless the snapshot identity came from a real header | ||
|
|
||
| A snapshot nothing is authorized to parse does not end the run. Core recovers | ||
| ARM64 code candidates from the instruction bytes, marks every one of them | ||
| heuristic and unnamed, and leaves libraries, classes, function names, the | ||
| original entry function and the ObjectPool unavailable with a diagnostic each. | ||
| `core_fallback_reason` says which condition it was. A pinned external backend is | ||
| refused by name instead, and an adapter that was authorized, ran, and failed is | ||
| still a failure. See [Core recovery](docs/cli-reference.md#core-recovery). | ||
|
|
||
| What the backends actually recover: | ||
|
|
||
| | Backend | Function names | Classes | ObjectPool | | ||
| | --- | --- | --- | --- | | ||
| | core recovery | none at all; code ranges are unnamed | none | unavailable | | ||
| | `internal` | none at all; code ranges are unnamed | none | carved strings, ordinal index space | | ||
| | `blutter` | scraped from Blutter's rendered source, heuristic | yes | Blutter `pp.txt` entries, ordinal index space | | ||
| | `r2flutter` | exact, from the AOT instruction table | yes, library attribution unavailable | real slots, resolvable from `x27` displacements | | ||
|
|
@@ -579,7 +631,7 @@ Recover readable behavior from Flutter AOT ARM64 binaries with enough semantic s | |
|
|
||
| ## Third-Party Credits | ||
|
|
||
| - `data/dart-profiles.json`: Dart snapshot hash-to-version and layout table imported from | ||
| - `data/dart-profiles.json`: Dart AOT snapshot layout profiles imported from | ||
| [radareorg/r2flutter](https://github.com/radareorg/r2flutter) (MIT). Rationale in | ||
| [docs/research-decisions.md](docs/research-decisions.md). | ||
| - `--adapter-backend r2-flutter` drives the same project as an external tool; it is not | ||
|
|
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: caverav/flutterdec
Length of output: 666
🏁 Script executed:
Repository: caverav/flutterdec
Length of output: 3507
🏁 Script executed:
Repository: caverav/flutterdec
Length of output: 298
Injection (CWE-94): Improper Control of Generation of Code ('Code Injection')
Reachability: External · Exploitability: Moderate
Avoid GitHub expression expansion in the shell.
The
pushtrigger acceptsv*tags, including names with shell command-substitution syntax. Direct${{ github.ref_name }}interpolation can execute commands on the runner.Pass both values through step environment variables and reference them as quoted shell variables.
Proposed fix
- name: Package artifact shell: bash + env: + REF_NAME: ${{ github.ref_name }} run: | set -euo pipefail os="${{ runner.os }}" arch="${{ runner.arch }}" out_dir="dist" mkdir -p "$out_dir" - archive="$out_dir/flutterdec-${{ github.ref_name }}-${os}-${arch}.tar.gz" + archive="$out_dir/flutterdec-${REF_NAME}-${os}-${arch}.tar.gz" - name: Verify archive runs off a checkout shell: bash - run: ./scripts/release-layout-smoke.sh "${{ env.archive }}" + env: + ARCHIVE: ${{ env.archive }} + run: ./scripts/release-layout-smoke.sh "$ARCHIVE"🧰 Tools
🪛 zizmor (1.29.0)
[warning] 93-93: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 Prompt for AI Agents
Source: Linters/SAST tools