mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Initial support for CONSTANT_Dynamic constant pool entry type
- Support for CONSTANT_Dynamic constant pool entry type - Fail-fast on unknown constant pool entry type (PR #1560) GitOrigin-RevId: 53990c2752281268d99807cdcb0a580cae1d7b75
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7049554673
commit
128ea3bcf8
+3
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.code;
|
||||
|
||||
@SuppressWarnings({"unused", "SpellCheckingInspection"})
|
||||
@@ -113,6 +113,7 @@ public interface CodeConstants {
|
||||
int CONSTANT_NameAndType = 12;
|
||||
int CONSTANT_MethodHandle = 15;
|
||||
int CONSTANT_MethodType = 16;
|
||||
int CONSTANT_Dynamic = 17;
|
||||
int CONSTANT_InvokeDynamic = 18;
|
||||
int CONSTANT_Module = 19;
|
||||
int CONSTANT_Package = 20;
|
||||
@@ -340,4 +341,4 @@ public interface CodeConstants {
|
||||
|
||||
String CLINIT_NAME = "<clinit>";
|
||||
String INIT_NAME = "<init>";
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.code.interpreter;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
|
||||
import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
|
||||
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
|
||||
import org.jetbrains.java.decompiler.struct.gen.DataPoint;
|
||||
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.util.ListStack;
|
||||
@@ -403,6 +404,14 @@ public final class InstructionImpact {
|
||||
case CodeConstants.CONSTANT_MethodHandle:
|
||||
stack.push(new VarType(((LinkConstant)constant).descriptor));
|
||||
break;
|
||||
case CodeConstants.CONSTANT_Dynamic:
|
||||
ck = pool.getLinkConstant(instr.operand(0));
|
||||
FieldDescriptor constDescriptor = FieldDescriptor.parseDescriptor(ck.descriptor);
|
||||
stack.push(constDescriptor.type);
|
||||
if (constDescriptor.type.stackSize == 2) {
|
||||
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CodeConstants.opc_aload:
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.struct;
|
||||
|
||||
public class MalformedClassFormatException extends RuntimeException {
|
||||
|
||||
public MalformedClassFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
+9
-1
@@ -1,9 +1,10 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.struct.consts;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
|
||||
import org.jetbrains.java.decompiler.struct.MalformedClassFormatException;
|
||||
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.NewClassNameBuilder;
|
||||
@@ -78,6 +79,7 @@ public class ConstantPool implements NewClassNameBuilder {
|
||||
case CodeConstants.CONSTANT_Fieldref:
|
||||
case CodeConstants.CONSTANT_Methodref:
|
||||
case CodeConstants.CONSTANT_InterfaceMethodref:
|
||||
case CodeConstants.CONSTANT_Dynamic:
|
||||
case CodeConstants.CONSTANT_InvokeDynamic:
|
||||
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort()));
|
||||
nextPass[1].set(i);
|
||||
@@ -87,6 +89,11 @@ public class ConstantPool implements NewClassNameBuilder {
|
||||
pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort()));
|
||||
nextPass[2].set(i);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Fail-fast on unknown constant pool entry.
|
||||
// We have no chance to process this class correctly.
|
||||
throw new MalformedClassFormatException(String.format("Unsupported constant pool entry type %d at index #%d! ", Byte.toUnsignedInt(tag), i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +124,7 @@ public class ConstantPool implements NewClassNameBuilder {
|
||||
case CodeConstants.CONSTANT_Methodref:
|
||||
case CodeConstants.CONSTANT_InterfaceMethodref:
|
||||
case CodeConstants.CONSTANT_NameAndType:
|
||||
case CodeConstants.CONSTANT_Dynamic:
|
||||
case CodeConstants.CONSTANT_InvokeDynamic:
|
||||
in.discard(4);
|
||||
break;
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.struct.consts;
|
||||
|
||||
public class LinkConstant extends PooledConstant {
|
||||
@@ -49,7 +49,7 @@ public class LinkConstant extends PooledConstant {
|
||||
descriptor = ref_info.descriptor;
|
||||
}
|
||||
else {
|
||||
if (type != CONSTANT_InvokeDynamic) {
|
||||
if (type != CONSTANT_InvokeDynamic && type != CONSTANT_Dynamic) {
|
||||
classname = pool.getPrimitiveConstant(index1).getString();
|
||||
}
|
||||
|
||||
@@ -72,4 +72,4 @@ public class LinkConstant extends PooledConstant {
|
||||
this.descriptor.equals(cn.descriptor) &&
|
||||
(this.type != CONSTANT_NameAndType || this.classname.equals(cn.classname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -3,6 +3,7 @@ package org.jetbrains.java.decompiler;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.struct.MalformedClassFormatException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -131,6 +132,12 @@ public class SingleClassesTest {
|
||||
@Test public void testPackageInfo() { doTest("pkg/package-info"); }
|
||||
@Test public void testIntVarMerge() { doTest("pkg/TestIntVarMerge"); }
|
||||
|
||||
@Test(expected = MalformedClassFormatException.class)
|
||||
public void testUnsupportedConstantPoolEntry() { doTest("java11/TestUnsupportedConstantPoolEntry"); }
|
||||
|
||||
@Test
|
||||
public void testDynamicConstantPoolEntry() { doTest("java11/TestDynamicConstantPoolEntry"); }
|
||||
|
||||
// TODO: fix all below
|
||||
//@Test public void testSwitchOnStrings() { doTest("pkg/TestSwitchOnStrings");}
|
||||
//@Test public void testUnionType() { doTest("pkg/TestUnionType"); }
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
package java11;
|
||||
|
||||
public class TestDynamicConstantPoolEntry {
|
||||
public static void main(String... var0) {
|
||||
System.out.println("This class file contains constant pool entry of type CONSTANT_Dynamic, not used in the bytecode.");
|
||||
}
|
||||
}
|
||||
|
||||
class 'java11/TestDynamicConstantPoolEntry' {
|
||||
method 'main ([Ljava/lang/String;)V' {
|
||||
0 4
|
||||
3 4
|
||||
5 4
|
||||
8 5
|
||||
}
|
||||
}
|
||||
|
||||
Lines mapping:
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
*
|
||||
* This code can be assembled with <a href="https://wiki.openjdk.java.net/display/CodeTools/asmtools">asmtools</a>
|
||||
* using <code>asmtools jcoder *.jcoder</code> command line.
|
||||
*
|
||||
* Test reading constant pool with CONSTANT_Dynamic entry at index #2. Dynamic constant didn't used in the bytecode and thus
|
||||
* should not affect decompiled code correctness in any way.
|
||||
*
|
||||
*/
|
||||
class java11/TestDynamicConstantPoolEntry {
|
||||
0xCAFEBABE;
|
||||
0; // minor version
|
||||
55; // version
|
||||
[] { // Constant Pool
|
||||
; // first element is empty
|
||||
String #29; // #1
|
||||
Dynamic 0s #25; // #2
|
||||
Field #35 #30; // #3
|
||||
Method #32 #36; // #4
|
||||
Method #22 #14; // #5
|
||||
Utf8 "TestDynamicConstantPoolEntry.jcoder"; // #6
|
||||
Utf8 "()V"; // #7
|
||||
Method #10 #9; // #8
|
||||
NameAndType #27 #13; // #9
|
||||
class #23; // #10
|
||||
Utf8 "Ljava/lang/Object;"; // #11
|
||||
Utf8 "<init>"; // #12
|
||||
Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #13
|
||||
NameAndType #12 #7; // #14
|
||||
Utf8 "out"; // #15
|
||||
Utf8 "java/io/PrintStream"; // #16
|
||||
MethodHandle 6b #8; // #17
|
||||
Utf8 "SourceFile"; // #18
|
||||
class #31; // #19
|
||||
Utf8 "java/lang/System"; // #20
|
||||
Utf8 "(Ljava/lang/String;)V"; // #21
|
||||
class #34; // #22
|
||||
Utf8 "java/lang/invoke/ConstantBootstraps"; // #23
|
||||
Utf8 "println"; // #24
|
||||
NameAndType #27 #11; // #25
|
||||
Utf8 "Ljava/io/PrintStream;"; // #26
|
||||
Utf8 "nullConstant"; // #27
|
||||
Utf8 "BootstrapMethods"; // #28
|
||||
Utf8 "This class file contains constant pool entry of type CONSTANT_Dynamic, not used in the bytecode."; // #29
|
||||
NameAndType #15 #26; // #30
|
||||
Utf8 "java11/TestDynamicConstantPoolEntry"; // #31
|
||||
class #16; // #32
|
||||
Utf8 "main"; // #33
|
||||
Utf8 "java/lang/Object"; // #34
|
||||
class #20; // #35
|
||||
NameAndType #24 #21; // #36
|
||||
Utf8 "([Ljava/lang/String;)V"; // #37
|
||||
Utf8 "Code"; // #38
|
||||
} // Constant Pool
|
||||
|
||||
0x0021; // access
|
||||
#19;// this_cpx
|
||||
#22;// super_cpx
|
||||
|
||||
[] { // Interfaces
|
||||
} // Interfaces
|
||||
|
||||
[] { // Fields
|
||||
} // Fields
|
||||
|
||||
[] { // Methods
|
||||
{ // method
|
||||
0x0001; // access
|
||||
#12; // name_index
|
||||
#7; // descriptor_index
|
||||
[] { // Attributes
|
||||
Attr(#38) { // Code
|
||||
1; // max_stack
|
||||
1; // max_locals
|
||||
Bytes[]{
|
||||
0x2AB70005B1;
|
||||
}
|
||||
[] { // Traps
|
||||
} // end Traps
|
||||
[] { // Attributes
|
||||
} // Attributes
|
||||
} // end Code
|
||||
} // Attributes
|
||||
}
|
||||
;
|
||||
{ // method
|
||||
0x0089; // access
|
||||
#33; // name_index
|
||||
#37; // descriptor_index
|
||||
[] { // Attributes
|
||||
Attr(#38) { // Code
|
||||
2; // max_stack
|
||||
1; // max_locals
|
||||
Bytes[]{
|
||||
0xB200031201B60004;
|
||||
0xB1;
|
||||
}
|
||||
[] { // Traps
|
||||
} // end Traps
|
||||
[] { // Attributes
|
||||
} // Attributes
|
||||
} // end Code
|
||||
} // Attributes
|
||||
}
|
||||
} // Methods
|
||||
|
||||
[] { // Attributes
|
||||
Attr(#18) { // SourceFile
|
||||
#6;
|
||||
} // end SourceFile
|
||||
;
|
||||
Attr(#28) { // BootstrapMethods
|
||||
[] { // bootstrap_methods
|
||||
{ // bootstrap_method
|
||||
#17; // bootstrap_method_ref
|
||||
[] { // bootstrap_arguments
|
||||
} // bootstrap_arguments
|
||||
} // bootstrap_method
|
||||
}
|
||||
} // end BootstrapMethods
|
||||
} // Attributes
|
||||
} // end class java11/TestDynamicConstantPoolEntry
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
*
|
||||
* This code can be assembled with <a href="https://wiki.openjdk.java.net/display/CodeTools/asmtools">asmtools</a>
|
||||
* using <code>asmtools jcoder *.jcoder</code> command line.
|
||||
*
|
||||
* Test handling constant pool entries of unknown type.
|
||||
*
|
||||
* Constant pool entry at index #10 has unknown tag 0xFF, not defined in JVMS.
|
||||
* We should refuse to process this *.class file as we has no chance to correctly detect constant pool entry size
|
||||
* and process rest of the class.
|
||||
*
|
||||
*/
|
||||
class java11/TestUnsupportedConstantPoolEntry {
|
||||
0xCAFEBABE;
|
||||
0; // minor version
|
||||
55; // version
|
||||
[] { // Constant Pool
|
||||
; // first element is empty
|
||||
Method #3 #7; // #1
|
||||
class #8; // #2
|
||||
class #9; // #3
|
||||
Utf8 "<init>"; // #4
|
||||
Utf8 "()V"; // #5
|
||||
Utf8 "Code"; // #6
|
||||
NameAndType #4 #5; // #7
|
||||
Utf8 "java11/TestUnsupportedConstantPoolEntry"; // #8
|
||||
Utf8 "java/lang/Object"; // #9
|
||||
0xFF #3; // #10
|
||||
} // Constant Pool
|
||||
|
||||
0x0021; // access
|
||||
#2;// this_cpx
|
||||
#3;// super_cpx
|
||||
|
||||
[] { // Interfaces
|
||||
} // Interfaces
|
||||
|
||||
[] { // Fields
|
||||
} // Fields
|
||||
|
||||
[] { // Methods
|
||||
{ // method
|
||||
0x0001; // access
|
||||
#4; // name_index
|
||||
#5; // descriptor_index
|
||||
[] { // Attributes
|
||||
Attr(#6) { // Code
|
||||
1; // max_stack
|
||||
1; // max_locals
|
||||
Bytes[]{
|
||||
0x2AB70001B1;
|
||||
}
|
||||
[] { // Traps
|
||||
} // end Traps
|
||||
[] { // Attributes
|
||||
} // Attributes
|
||||
} // end Code
|
||||
} // Attributes
|
||||
}
|
||||
} // Methods
|
||||
|
||||
[] { // Attributes
|
||||
} // Attributes
|
||||
} // end class java11/TestUnsupportedConstantPoolEntry
|
||||
Reference in New Issue
Block a user