Skip to content

fix(core): restore enum initialized with external SGET field (#2618)#2918

Open
gaurav0107 wants to merge 1 commit into
skylot:masterfrom
gaurav0107:fix/2618-core-enum-cannot-be-restored-using-exter
Open

fix(core): restore enum initialized with external SGET field (#2618)#2918
gaurav0107 wants to merge 1 commit into
skylot:masterfrom
gaurav0107:fix/2618-core-enum-cannot-be-restored-using-exter

Conversation

@gaurav0107

Copy link
Copy Markdown

Problem

Fixes #2618. When a Dalvik enum's constant constructors take an argument whose SSA value is a static-field read (SGET) of an external constant — typically a constant of another enum, reused across several constants so R8 keeps it in a register instead of inlining it — EnumVisitor fails to restore the enum:

jadx.core.utils.exceptions.JadxRuntimeException: Init of enum field '...' uses external variables
	at jadx.core.dex.visitors.EnumVisitor.createEnumFieldByConstructor(EnumVisitor.java:485)

The class is then emitted as a plain class with the enum modifier and super class stripped.

Fix

inlineExternalRegs already inlines a constructor argument that references another constant of the same enum. This extends it: when the argument's SSA value is instead assigned by an external SGET, inline a copy of that SGET into the enum-field initializer. Existing behaviour is unchanged — the new branch is only reached where the old code returned null (and threw).

Test

Adds TestEnumExternalSget (multi-file SmaliTest, reduced from the reporter's sample): an enum whose constants pass reused ExtEnum.* values to the constructor. Before the fix the class is emitted as class with the enum-restore-failure warning; after, it is restored as enum TestEnumExternalSget with A(ExtEnum.FIRST), B(ExtEnum.FIRST), C(ExtEnum.SECOND).

Verified locally: the full jadx.tests.integration.enums.* package is green (33 tests), the whole :jadx-core:test suite shows no new failures versus master, and :jadx-core:spotlessCheck passes.

…2618)

An enum constant constructor can take an argument whose value is a static
field read (SGET) of an external constant, e.g. a constant of another enum
that is reused across several enum fields. R8 keeps such a reused value in a
register instead of inlining it, so it reaches EnumVisitor as a register
argument.

inlineExternalRegs only handled arguments referencing another constant of
the same enum and aborted restoration with
"Init of enum field '...' uses external variables" for the external SGET
case, emitting the class without the enum modifier.

Inline the external SGET into the enum field initializer, mirroring how
same-enum references are already inlined, so the enum is restored correctly.

Fixes skylot#2618
@gaurav0107
gaurav0107 marked this pull request as ready for review July 15, 2026 23:27
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.

[core] Enum cannot be restored, using external variable (SGET)

1 participant