IDEA-129221 (tolerate invalid signature attributes)
This commit is contained in:
parent
e2f7d09f37
commit
e90f1de039
@ -626,12 +626,14 @@ public class ClassWriter {
|
|||||||
StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttributes().getWithKey("Signature");
|
StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttributes().getWithKey("Signature");
|
||||||
if (attr != null) {
|
if (attr != null) {
|
||||||
descriptor = GenericMain.parseMethodSignature(attr.getSignature());
|
descriptor = GenericMain.parseMethodSignature(attr.getSignature());
|
||||||
int actualParams = md.params.length;
|
if (descriptor != null) {
|
||||||
if (isEnum && init) actualParams -= 2;
|
int actualParams = md.params.length;
|
||||||
if (actualParams != descriptor.params.size()) {
|
if (isEnum && init) actualParams -= 2;
|
||||||
String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor();
|
if (actualParams != descriptor.params.size()) {
|
||||||
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
|
String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor();
|
||||||
descriptor = null;
|
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
|
||||||
|
descriptor = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.struct.gen.generics;
|
|||||||
|
|
||||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||||
|
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
|
||||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -24,7 +25,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class GenericMain {
|
public class GenericMain {
|
||||||
|
|
||||||
private static final String[] typeNames = new String[]{
|
private static final String[] typeNames = {
|
||||||
"byte",
|
"byte",
|
||||||
"char",
|
"char",
|
||||||
"double",
|
"double",
|
||||||
@ -36,63 +37,80 @@ public class GenericMain {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static GenericClassDescriptor parseClassSignature(String signature) {
|
public static GenericClassDescriptor parseClassSignature(String signature) {
|
||||||
|
String original = signature;
|
||||||
|
try {
|
||||||
|
GenericClassDescriptor descriptor = new GenericClassDescriptor();
|
||||||
|
|
||||||
GenericClassDescriptor descriptor = new GenericClassDescriptor();
|
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
||||||
|
|
||||||
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
String superCl = GenericType.getNextType(signature);
|
||||||
|
descriptor.superclass = new GenericType(superCl);
|
||||||
|
|
||||||
String supercl = GenericType.getNextType(signature);
|
signature = signature.substring(superCl.length());
|
||||||
descriptor.superclass = new GenericType(supercl);
|
while (signature.length() > 0) {
|
||||||
|
String superIf = GenericType.getNextType(signature);
|
||||||
|
descriptor.superinterfaces.add(new GenericType(superIf));
|
||||||
|
signature = signature.substring(superIf.length());
|
||||||
|
}
|
||||||
|
|
||||||
signature = signature.substring(supercl.length());
|
return descriptor;
|
||||||
while (signature.length() > 0) {
|
}
|
||||||
String superintr = GenericType.getNextType(signature);
|
catch (RuntimeException e) {
|
||||||
descriptor.superinterfaces.add(new GenericType(superintr));
|
DecompilerContext.getLogger().writeMessage("Invalid signature: " + original, IFernflowerLogger.Severity.WARN);
|
||||||
signature = signature.substring(superintr.length());
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GenericFieldDescriptor parseFieldSignature(String signature) {
|
public static GenericFieldDescriptor parseFieldSignature(String signature) {
|
||||||
GenericFieldDescriptor descriptor = new GenericFieldDescriptor();
|
try {
|
||||||
descriptor.type = new GenericType(signature);
|
GenericFieldDescriptor descriptor = new GenericFieldDescriptor();
|
||||||
return descriptor;
|
descriptor.type = new GenericType(signature);
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
catch (RuntimeException e) {
|
||||||
|
DecompilerContext.getLogger().writeMessage("Invalid signature: " + signature, IFernflowerLogger.Severity.WARN);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GenericMethodDescriptor parseMethodSignature(String signature) {
|
public static GenericMethodDescriptor parseMethodSignature(String signature) {
|
||||||
|
String original = signature;
|
||||||
|
try {
|
||||||
|
GenericMethodDescriptor descriptor = new GenericMethodDescriptor();
|
||||||
|
|
||||||
GenericMethodDescriptor descriptor = new GenericMethodDescriptor();
|
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
||||||
|
|
||||||
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
int to = signature.indexOf(")");
|
||||||
|
String pars = signature.substring(1, to);
|
||||||
|
signature = signature.substring(to + 1);
|
||||||
|
|
||||||
int to = signature.indexOf(")");
|
while (pars.length() > 0) {
|
||||||
String pars = signature.substring(1, to);
|
String par = GenericType.getNextType(pars);
|
||||||
signature = signature.substring(to + 1);
|
descriptor.params.add(new GenericType(par));
|
||||||
|
pars = pars.substring(par.length());
|
||||||
while (pars.length() > 0) {
|
|
||||||
String par = GenericType.getNextType(pars);
|
|
||||||
descriptor.params.add(new GenericType(par));
|
|
||||||
pars = pars.substring(par.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
String par = GenericType.getNextType(signature);
|
|
||||||
descriptor.ret = new GenericType(par);
|
|
||||||
signature = signature.substring(par.length());
|
|
||||||
|
|
||||||
if (signature.length() > 0) {
|
|
||||||
String[] excs = signature.split("\\^");
|
|
||||||
|
|
||||||
for (int i = 1; i < excs.length; i++) {
|
|
||||||
descriptor.exceptions.add(new GenericType(excs[i]));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return descriptor;
|
String par = GenericType.getNextType(signature);
|
||||||
|
descriptor.ret = new GenericType(par);
|
||||||
|
signature = signature.substring(par.length());
|
||||||
|
|
||||||
|
if (signature.length() > 0) {
|
||||||
|
String[] exceptions = signature.split("\\^");
|
||||||
|
|
||||||
|
for (int i = 1; i < exceptions.length; i++) {
|
||||||
|
descriptor.exceptions.add(new GenericType(exceptions[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
catch (RuntimeException e) {
|
||||||
|
DecompilerContext.getLogger().writeMessage("Invalid signature: " + original, IFernflowerLogger.Severity.WARN);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseFormalParameters(String signature, List<String> fparameters, List<List<GenericType>> fbounds) {
|
private static String parseFormalParameters(String signature, List<String> parameters, List<List<GenericType>> bounds) {
|
||||||
|
|
||||||
if (signature.charAt(0) != '<') {
|
if (signature.charAt(0) != '<') {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
@ -120,10 +138,10 @@ public class GenericMain {
|
|||||||
signature = signature.substring(index + 1);
|
signature = signature.substring(index + 1);
|
||||||
|
|
||||||
while (value.length() > 0) {
|
while (value.length() > 0) {
|
||||||
int parto = value.indexOf(":");
|
int to = value.indexOf(":");
|
||||||
|
|
||||||
String param = value.substring(0, parto);
|
String param = value.substring(0, to);
|
||||||
value = value.substring(parto + 1);
|
value = value.substring(to + 1);
|
||||||
|
|
||||||
List<GenericType> lstBounds = new ArrayList<GenericType>();
|
List<GenericType> lstBounds = new ArrayList<GenericType>();
|
||||||
|
|
||||||
@ -146,8 +164,8 @@ public class GenericMain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fparameters.add(param);
|
parameters.add(param);
|
||||||
fbounds.add(lstBounds);
|
bounds.add(lstBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return signature;
|
return signature;
|
||||||
@ -162,8 +180,7 @@ public class GenericMain {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTypeName(GenericType type) {
|
private static String getTypeName(GenericType type) {
|
||||||
|
|
||||||
int tp = type.type;
|
int tp = type.type;
|
||||||
if (tp <= CodeConstants.TYPE_BOOLEAN) {
|
if (tp <= CodeConstants.TYPE_BOOLEAN) {
|
||||||
return typeNames[tp];
|
return typeNames[tp];
|
||||||
@ -197,9 +214,9 @@ public class GenericMain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericType genpar = type.getArguments().get(i);
|
GenericType genPar = type.getArguments().get(i);
|
||||||
if (genpar != null) {
|
if (genPar != null) {
|
||||||
buffer.append(getGenericCastTypeName(genpar));
|
buffer.append(getGenericCastTypeName(genPar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.append(">");
|
buffer.append(">");
|
||||||
@ -208,11 +225,10 @@ public class GenericMain {
|
|||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("invalid type");
|
throw new RuntimeException("Invalid type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildJavaClassName(GenericType type) {
|
private static String buildJavaClassName(GenericType type) {
|
||||||
|
|
||||||
String name = "";
|
String name = "";
|
||||||
for (GenericType tp : type.getEnclosingClasses()) {
|
for (GenericType tp : type.getEnclosingClasses()) {
|
||||||
name += tp.value + "$";
|
name += tp.value + "$";
|
||||||
|
@ -43,30 +43,32 @@ public class SingleClassesTest {
|
|||||||
fixture = null;
|
fixture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testClassFields() { doTest("TestClassFields"); }
|
@Test public void testClassFields() { doTest("pkg/TestClassFields"); }
|
||||||
@Test public void testClassLambda() { doTest("TestClassLambda"); }
|
@Test public void testClassLambda() { doTest("pkg/TestClassLambda"); }
|
||||||
@Test public void testClassLoop() { doTest("TestClassLoop"); }
|
@Test public void testClassLoop() { doTest("pkg/TestClassLoop"); }
|
||||||
@Test public void testClassSwitch() { doTest("TestClassSwitch"); }
|
@Test public void testClassSwitch() { doTest("pkg/TestClassSwitch"); }
|
||||||
@Test public void testClassTypes() { doTest("TestClassTypes"); }
|
@Test public void testClassTypes() { doTest("pkg/TestClassTypes"); }
|
||||||
@Test public void testClassVar() { doTest("TestClassVar"); }
|
@Test public void testClassVar() { doTest("pkg/TestClassVar"); }
|
||||||
@Test public void testClassNestedInitializer() { doTest("TestClassNestedInitializer"); }
|
@Test public void testClassNestedInitializer() { doTest("pkg/TestClassNestedInitializer"); }
|
||||||
@Test public void testClassCast() { doTest("TestClassCast"); }
|
@Test public void testClassCast() { doTest("pkg/TestClassCast"); }
|
||||||
@Test public void testDeprecations() { doTest("TestDeprecations"); }
|
@Test public void testDeprecations() { doTest("pkg/TestDeprecations"); }
|
||||||
@Test public void testExtendsList() { doTest("TestExtendsList"); }
|
@Test public void testExtendsList() { doTest("pkg/TestExtendsList"); }
|
||||||
@Test public void testMethodParameters() { doTest("TestMethodParameters"); }
|
@Test public void testMethodParameters() { doTest("pkg/TestMethodParameters"); }
|
||||||
@Test public void testCodeConstructs() { doTest("TestCodeConstructs"); }
|
@Test public void testCodeConstructs() { doTest("pkg/TestCodeConstructs"); }
|
||||||
@Test public void testConstants() { doTest("TestConstants"); }
|
@Test public void testConstants() { doTest("pkg/TestConstants"); }
|
||||||
@Test public void testEnum() { doTest("TestEnum"); }
|
@Test public void testEnum() { doTest("pkg/TestEnum"); }
|
||||||
@Test public void testDebugSymbols() { doTest("TestDebugSymbols"); }
|
@Test public void testDebugSymbols() { doTest("pkg/TestDebugSymbols"); }
|
||||||
|
@Test public void testInvalidMethodSignature() { doTest("InvalidMethodSignature"); }
|
||||||
|
|
||||||
private void doTest(final String testName) {
|
private void doTest(String testFile) {
|
||||||
try {
|
try {
|
||||||
File classFile = new File(fixture.getTestDataDir(), "/classes/pkg/" + testName + ".class");
|
File classFile = new File(fixture.getTestDataDir(), "/classes/" + testFile + ".class");
|
||||||
assertTrue(classFile.isFile());
|
assertTrue(classFile.isFile());
|
||||||
|
String testName = classFile.getName().replace(".class", "");
|
||||||
|
|
||||||
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
||||||
for (File inner : collectClasses(classFile)) {
|
for (File file : collectClasses(classFile)) {
|
||||||
decompiler.addSpace(inner, true);
|
decompiler.addSpace(file, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
decompiler.decompileContext();
|
decompiler.decompileContext();
|
||||||
|
BIN
testData/classes/InvalidMethodSignature.class
Normal file
BIN
testData/classes/InvalidMethodSignature.class
Normal file
Binary file not shown.
26
testData/results/InvalidMethodSignature.dec
Normal file
26
testData/results/InvalidMethodSignature.dec
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package a.a.a.a.e.f;
|
||||||
|
|
||||||
|
import a.a.a.a.a.k;
|
||||||
|
import a.a.a.a.c.c;
|
||||||
|
import a.a.a.a.c.j;
|
||||||
|
import a.a.a.a.e.bg;
|
||||||
|
import a.a.a.a.e.f.b;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
class i implements bg {
|
||||||
|
private final j a;
|
||||||
|
private final b b;
|
||||||
|
|
||||||
|
i(b var1, j var2) {
|
||||||
|
this.b = var1;
|
||||||
|
this.a = var2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(c var1, k var2, boolean var3) {
|
||||||
|
File var4 = this.a.b().a(var1);
|
||||||
|
b.a(this.b).add(var4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(a.a.a.a.c.b var1) {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user