Skip to content

Releases: ejfkdev/ddc

v0.1.8

Choose a tag to compare

@github-actions github-actions released this 21 Sep 09:05
v0.1.8
e635b8f

v0.1.8 — quality rounds 59-64 + determinism hardening

Code quality (gold standard: full javac + android.jar, 4 real-world APKs):

  • LOCAL-OK-gated renames for field-obscured nested types (JLS 6.4.2
    shadow family, flutter g$i shape): a full-corpus dex reference scan
    (new refscan module) gates each rename to provably file-local blast
    radius, plus the shadow-package twin rule. Ungated global renaming
    was measured catastrophic on conflict-dense corpora (weibo +36916).
  • Conditional-super restructuring, 5 mechanical shapes: if/else branch
    merge with per-arg ternaries, straight-line inline-hoist, duplicate
    delegation dedup (R8 path-duplicated Kotlin default-arg bridges),
    throw-guard branches, chained guards via recursive normalization.
    "super must be first statement" errors: 513 -> 142.
  • Enum constant ctor args resolved through clinit reaching-definitions
    (R8 register reuse across constant constructions): no more
    DEBUG(var0) dummy-name garbage.
  • Static-field owner on synthetic holders prints the concrete anonymous
    name (LongMath$1.$SwitchMap$..., was Object.$SwitchMap$...).

Determinism (byte-identical output across runs restored):

  • Root cause: a process-wide shared fallback VarInfo cached whichever
    dangling var id hit it first (jdc-core) — now per-id.
  • Accessor code snapshotted before image retirement (inline_accessors
    cross-image reads raced retirement).
  • CodeItem::parse only reads the catch-handler list when tries exist
    (spec 8.3.1) — exact-sized snapshots used to fail parsing, silently
    disabling accessor inlining corpus-wide.
  • jdc-core walk gains a deterministic work budget (Σ universe per
    visit) behind the wall-clock backstop.

Gold standard totals (vs v0.1.7): reqable 15987 -> 14658,
weibo 155335 -> 154560, lark 68842 -> 64222, weixin 298275 -> 297003
(net -7996). Decomp times unchanged (weibo ~6.5s, weixin ~12s).
67 tests green; zero compiler/clippy warnings in ddc + jdc-core 0.2.3
(its never_loop correctness lint fixed); jdc-core bumped to 0.2.3.

Full Changelog: v0.1.7...v0.1.8

v0.1.7

Choose a tag to compare

@github-actions github-actions released this 20 Sep 15:22
v0.1.7
d5b151b

v0.1.7 — correctness: framework nesting, clinit returns, field casts

  • External framework nested references now dot correctly
    (android.os.Parcelable.Creator instead of Parcelable$Creator).
  • Static initializers no longer contain illegal returns
    ("return outside method": 184 -> 2 on reqable).
  • Field reads on Object-widened receivers cast to the declaring class.
  • Full-javac gate (reqable + android.jar): 20,895 semantic errors
    (-50.5% vs 0.1.5); syntax gate zero across the corpus; deterministic.
  • jdc-core 0.2.2.

Full Changelog: v0.1.6...v0.1.7

v0.1.6

Choose a tag to compare

@github-actions github-actions released this 20 Sep 14:11
v0.1.6
c86f32d

v0.1.6 — output quality: eight fix rounds, semantic errors halved

  • Real local-variable names from debug_info; true enum declarations.
  • Name-collision classes eliminated (nested chains, sanitizer
    collapses, covariant overrides, package-leaf shadowing — alone
    -12.5k "cannot find symbol" on reqable).
  • null/long/cast/super correctness fixes; directional type evidence.
  • Full-javac gate (with android.jar) on reqable: 42,251 -> 21,193
    semantic errors (-49.9%). Syntax gate stays at zero across the
    1.18M-file corpus; output deterministic; performance unchanged.
  • jdc-core 0.2.1.

Full Changelog: v0.1.5...v0.1.6

v0.1.5

Choose a tag to compare

@github-actions github-actions released this 20 Sep 09:39
v0.1.5
0ab9378

v0.1.5 — output quality: real local names + compilability fixes

  • Real local-variable names from debug_info (type-gated, cross-block
    unified): s() now reads String s(byte[] enc, int k) with out/i.
  • Lab-package feedback fully root-caused: 0 javac errors (0.1.4: 39).
  • javac full-compile gate fixes: nested-class name-chain renames
    (lark already-defined 22316 -> 93), nested reference prefixes,
    catch-parameter double declaration, super() ordering, duplicate
    covariant methods (weibo 14871 -> 971).
  • Perf round: weixin 18.2 -> 10.6s, qq -25%, WhatsApp -38%;
    deterministic output run-to-run.
  • jdc-core 0.2.0, ddc-dex 0.2.1.

Full Changelog: v0.1.4...v0.1.5

v0.1.4

Choose a tag to compare

@github-actions github-actions released this 19 Sep 18:51
v0.1.4
ff1ef2f

v0.1.4

Output quality — four new body-cleanup passes, all on by default:

  • jadx-style local names: a synthetic v12/p3 never survives when a
    better name exists (Kotlin Intrinsics parameter strings, the defining
    call, jadx's type-alias table with the class-name fallback).
  • Kotlin null-check elision: statement-position
    Intrinsics.checkNotNull… calls drop after their strings feed the
    naming pass (lark: 59,106 → 9).
  • Synthetic-accessor inlining: access$NNN static bridges inline at
    their call sites — identity, field getter, method forwarder, with d8
    APM trace wrappers tolerated (lark: 43% of 9,214 call sites).
  • IntDef constant rendering, now built-in: setVisibility(8) renders
    as android.view.View.GONE with no flags — the android-37 domain
    table ships as a readable, diffable
    platform_symbols.txt that build.rs compresses into the binary;
    --symbols <platform-dir> overrides.

Verified: lark (118,502 files) and weixin (239,599 files) pass the
javac parse gate with zero errors; timing within noise (reqable
0.29s, lark 6.4s, weixin 17.5s). 67 tests, clippy zero.

Full Changelog: v0.1.3...v0.1.4

v0.1.3

Choose a tag to compare

@github-actions github-actions released this 19 Sep 15:31
v0.1.3
88b2658

v0.1.3

  • Fixed: ddc aborted before doing any work on archives whose central-
    directory size crossed the EOCD entry-count field — the u16 field was
    read as u32, so Vec::with_capacity asked the allocator for ~200 GB
    and the process died on the spot. Found, root-caused and fixed by
    @dashanlkk in #1 (with a regression test that reproduces the original
    202 GB allocation).
  • Fixed: quitting a pager (ddc app.apk -o - | less) no longer panics
    with "failed printing to stdout: Broken pipe" — SIGPIPE keeps its
    default disposition.

What's Changed

  • fix: read the EOCD entry count as u16 (ddc aborted on archives with a large cd_size) by @dashanlkk in #1

New Contributors

Full Changelog: v0.1.2...v0.1.3

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 19 Sep 14:52
v0.1.2
47993d3

v0.1.2

Highlights since v0.1.1:

  • Full-corpus validation: 39 real-world APKs (6.4 GB, 5.4M classes)
    decompile to 4,081,503 files that ALL pass javac's parse phase —
    zero syntax errors. Seven obfuscated-name defects found and fixed
    along the way (case-renamed class headers, the lone-underscore
    reserved identifier, restricted type names like 'var', digit-start
    names, R8 trailing-'$' class names, Kotlin bare yield() calls,
    fake dex entries no longer abort a run). docs/validation.md.

  • ddc info is now the one orientation command: an app-context header
    (label resolved through resources.arsc, package, version, launcher,
    sdk, size, md5) above the per-dex table.

  • Performance: the per-invoke proto re-parse is gone (fixpoint phase
    CPU 23.5s -> 11.3s on lark, total decompile CPU -35%); method
    names/descriptors share per-dex tables as Arc (peak RSS
    -81MB on lark).

  • weixin full-decompile stack overflow fixed (forward_single_use
    inlining a def-reference cycle).

  • Parser: dex-LIKE entries (encrypted payloads) are skipped with a
    notice instead of failing the whole run.

jdc-core 0.1.10; ddc-dex 0.2.0 (breaking: proto_params -> &[u32]).

Full Changelog: v0.1.1...v0.1.2

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 18 Sep 21:58
v0.1.1
c9e052c

ddc 0.1.1 — javac-verified output

Full decompile: weibo (226MB, 98k classes) 5.98s, qq (374MB) 18s,
whatsapp 139MB 9s with case-variant class pairs all preserved
(99,276 files). 20+ progressive subcommands answering in <=0.9s.
Every output file of seven real APKs (1,085,000 files) passes javac
with zero syntax errors. Bilingual CLI and docs. Built on
jdc-core 0.1.9.

Also in this tag: zero compiler/clippy warnings, quality round
(alloc-free fast paths, single-allocation descriptors).

Full Changelog: v0.1.0...v0.1.1

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 18 Sep 12:20
v0.1.0
db26de9
ddc 0.1.0 — first public release

DEX → Java decompiler in Rust. Full decompile of a 226MB/20-dex APK
in ~6s; 20+ progressive-analysis subcommands answering in milliseconds;
DEX 035-041, XAPK/APKS/APKM containers, invoke-custom; bilingual CLI;
reproducible output. Built on jdc-core 0.1.6.