fix: don't run class process from visitors to avoid deadlock (#743)
This commit is contained in:
@@ -14,7 +14,6 @@ import static jadx.core.dex.nodes.ProcessState.LOADED;
|
||||
import static jadx.core.dex.nodes.ProcessState.NOT_LOADED;
|
||||
import static jadx.core.dex.nodes.ProcessState.PROCESS_COMPLETE;
|
||||
import static jadx.core.dex.nodes.ProcessState.PROCESS_STARTED;
|
||||
import static jadx.core.dex.nodes.ProcessState.UNLOADED;
|
||||
|
||||
public final class ProcessClass {
|
||||
|
||||
@@ -27,8 +26,7 @@ public final class ProcessClass {
|
||||
process(topParentClass);
|
||||
return;
|
||||
}
|
||||
if (cls.getState() == PROCESS_COMPLETE
|
||||
|| cls.getState() == UNLOADED) {
|
||||
if (cls.getState().isProcessed()) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -591,10 +591,8 @@ public class InsnGen {
|
||||
private void makeConstructor(ConstructorInsn insn, CodeWriter code)
|
||||
throws CodegenException {
|
||||
ClassNode cls = mth.dex().resolveClass(insn.getClassType());
|
||||
if (cls != null) {
|
||||
cls.loadAndProcess();
|
||||
}
|
||||
if (cls != null && cls.isAnonymous() && !fallback) {
|
||||
cls.ensureProcessed();
|
||||
inlineAnonymousConstructor(code, cls, insn);
|
||||
return;
|
||||
}
|
||||
@@ -787,21 +785,10 @@ public class InsnGen {
|
||||
*/
|
||||
private boolean processOverloadedArg(CodeWriter code, InsnNode insn, MethodNode callMth, InsnArg arg, int origPos) {
|
||||
List<ArgType> argTypes = callMth.getArgTypes();
|
||||
if (argTypes == null) {
|
||||
// try to load class
|
||||
callMth.getParentClass().loadAndProcess();
|
||||
argTypes = callMth.getArgTypes();
|
||||
}
|
||||
ArgType origType;
|
||||
if (argTypes == null) {
|
||||
mth.addComment("JADX INFO: used method not loaded: " + callMth + ", types can be incorrect");
|
||||
origType = callMth.getMethodInfo().getArgumentsTypes().get(origPos);
|
||||
} else {
|
||||
origType = argTypes.get(origPos);
|
||||
if (origType.isGenericType() && !callMth.getParentClass().equals(mth.getParentClass())) {
|
||||
// cancel cast
|
||||
return false;
|
||||
}
|
||||
ArgType origType = argTypes.get(origPos);
|
||||
if (origType.isGenericType() && !callMth.getParentClass().equals(mth.getParentClass())) {
|
||||
// cancel cast
|
||||
return false;
|
||||
}
|
||||
ArgType castType = null;
|
||||
if (insn instanceof CallMthInterface && origType.containsGenericType()) {
|
||||
|
||||
@@ -110,9 +110,10 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
}
|
||||
|
||||
loadAnnotations(cls);
|
||||
|
||||
initAccessFlags(cls);
|
||||
parseClassSignature();
|
||||
setFieldsTypesFromSignature();
|
||||
methods.forEach(MethodNode::initMethodTypes);
|
||||
|
||||
int sfIdx = cls.getSourceFileIndex();
|
||||
if (sfIdx != DexNode.NO_INDEX) {
|
||||
@@ -120,21 +121,26 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
addSourceFilenameAttr(fileName);
|
||||
}
|
||||
|
||||
// restore original access flags from dalvik annotation if present
|
||||
int accFlagsValue;
|
||||
Annotation a = getAnnotation(Consts.DALVIK_INNER_CLASS);
|
||||
if (a != null) {
|
||||
accFlagsValue = (Integer) a.getValues().get("accessFlags");
|
||||
} else {
|
||||
accFlagsValue = cls.getAccessFlags();
|
||||
}
|
||||
this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);
|
||||
buildCache();
|
||||
} catch (Exception e) {
|
||||
throw new JadxRuntimeException("Error decode class: " + clsInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore original access flags from Dalvik annotation if present
|
||||
*/
|
||||
private void initAccessFlags(ClassDef cls) {
|
||||
int accFlagsValue;
|
||||
Annotation a = getAnnotation(Consts.DALVIK_INNER_CLASS);
|
||||
if (a != null) {
|
||||
accFlagsValue = (Integer) a.getValues().get("accessFlags");
|
||||
} else {
|
||||
accFlagsValue = cls.getAccessFlags();
|
||||
}
|
||||
this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);
|
||||
}
|
||||
|
||||
// empty synthetic class
|
||||
public ClassNode(DexNode dex, String name, int accessFlags) {
|
||||
this.dex = dex;
|
||||
@@ -247,8 +253,13 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
this.addAttr(new SourceFileAttr(fileName));
|
||||
}
|
||||
|
||||
public void loadAndProcess() {
|
||||
ProcessClass.process(this);
|
||||
public void ensureProcessed() {
|
||||
ClassNode topClass = getTopParentClass();
|
||||
ProcessState topState = topClass.getState();
|
||||
if (!topState.isProcessed()) {
|
||||
throw new JadxRuntimeException("Expected class to be processed at this point,"
|
||||
+ " class: " + topClass + ", state: " + topState);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized ICodeInfo decompile() {
|
||||
|
||||
@@ -121,14 +121,15 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
if (noCode) {
|
||||
regsCount = 0;
|
||||
codeSize = 0;
|
||||
initMethodTypes();
|
||||
// TODO: registers not needed without code
|
||||
initArguments(this.argTypes);
|
||||
return;
|
||||
}
|
||||
|
||||
DexNode dex = parentClass.dex();
|
||||
Code mthCode = dex.readCode(methodData);
|
||||
this.regsCount = mthCode.getRegistersSize();
|
||||
initMethodTypes();
|
||||
initArguments(this.argTypes);
|
||||
|
||||
InsnDecoder decoder = new InsnDecoder(this);
|
||||
decoder.decodeInsns(mthCode);
|
||||
@@ -172,7 +173,7 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
}
|
||||
}
|
||||
|
||||
private void initMethodTypes() {
|
||||
public void initMethodTypes() {
|
||||
List<ArgType> types = parseSignature();
|
||||
if (types == null) {
|
||||
this.retType = mthInfo.getReturnType();
|
||||
@@ -180,7 +181,6 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
} else {
|
||||
this.argTypes = types;
|
||||
}
|
||||
initArguments(this.argTypes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -253,11 +253,11 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return null only if method not yet loaded
|
||||
*/
|
||||
@Nullable
|
||||
@NotNull
|
||||
public List<ArgType> getArgTypes() {
|
||||
if (argTypes == null) {
|
||||
throw new JadxRuntimeException("Method types not initialized: " + this);
|
||||
}
|
||||
return argTypes;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,5 +6,13 @@ public enum ProcessState {
|
||||
PROCESS_STARTED,
|
||||
PROCESS_COMPLETE,
|
||||
GENERATED,
|
||||
UNLOADED
|
||||
UNLOADED;
|
||||
|
||||
public boolean isLoaded() {
|
||||
return this != NOT_LOADED;
|
||||
}
|
||||
|
||||
public boolean isProcessed() {
|
||||
return this == PROCESS_COMPLETE || this == GENERATED || this == UNLOADED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,6 @@ public class RootNode {
|
||||
public List<GenericInfo> getClassGenerics(ArgType type) {
|
||||
ClassNode classNode = resolveClass(ClassInfo.fromType(this, type));
|
||||
if (classNode != null) {
|
||||
classNode.loadAndProcess();
|
||||
return classNode.getGenerics();
|
||||
}
|
||||
NClass clsDetails = getClsp().getClsDetails(type);
|
||||
|
||||
@@ -275,7 +275,6 @@ public class ModVisitor extends AbstractVisitor {
|
||||
if (!mth.getParentClass().getInnerClasses().contains(classNode)) {
|
||||
return;
|
||||
}
|
||||
classNode.loadAndProcess();
|
||||
Map<InsnArg, FieldNode> argsMap = getArgsToFieldsMapping(callMthNode, co);
|
||||
if (argsMap.isEmpty() && !callMthNode.getArgRegs().isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -27,6 +27,7 @@ import jadx.api.ICodeInfo;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.JadxInternalAccess;
|
||||
import jadx.core.ProcessClass;
|
||||
import jadx.core.codegen.CodeGen;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
@@ -223,7 +224,7 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
}
|
||||
|
||||
protected void decompileWithoutUnload(JadxDecompiler jadx, ClassNode cls) {
|
||||
cls.loadAndProcess();
|
||||
ProcessClass.process(cls);
|
||||
generateClsCode(cls);
|
||||
// don't unload class
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user