提交 db892adf 编写于 作者: S Skylot

fix: don't run class process from visitors to avoid deadlock (#743)

上级 1cbaad3e
......@@ -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
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册