[PATCH][asmtools] Fix incorrect handling of some CPX2 constant pool entries by JDIS

Maxim Degtyarev mdegtyarev at gmail.com
Mon Mar 12 23:52:50 UTC 2018


The proposed patch (see attached file jdis-cpx2-bug.diff.txt) address
incorrect handling of some constant pool entries represented with CPX2
class by ASMTOOLS JDIS.

JDIS incorrectly assume that field CPX2::value1 is always used to hold
index of constant pool entry of type CONSTANT_CLASS.
This assumption is valid only for entries of type CONSTANT_FIELD,
CONSTANT_METHOD and CONSTANT_INTERFACEMETHOD.
For CONSTANT_NAMEANDTYPE, CONSTANT_METHODHANDLE, CONSTANT_DYNAMIC and
CONSTANT_INVOKEDYNAMIC this assumption is wrong.
As a result asmtools jdis may produce malformed output for valid input.

Example:

public class Test {

    // Force `class Test` entry appear in the constant pool before
InvokeDynamic entries.
    public Class<?> CLASS = Test.class;

    private static Runnable[] workers = {
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test"),
        () -> System.out.println("Test")
    };

    public static void main(String... args) {

        for(Runnable worker : workers) {
            worker.run();
        }

    }

}

One of invokedynamic instructions may be rendered by jdis as

        invokedynamic    InvokeDynamic run:"()Ljava/lang/Runnable;";

instead of

        invokedynamic    InvokeDynamic
REF_invokeStatic:java/lang/invoke/LambdaMetafactory.metafactory:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;":run:"()Ljava/lang/Runnable;"
MethodType "()V", MethodHandle
REF_invokeStatic:Test.lambda$static$1:"()V", MethodType "()V";
-------------- next part --------------
# HG changeset patch
# User maccimo
# Date 1520880268 -10800
#      Mon Mar 12 21:44:28 2018 +0300
# Node ID f5e62b0fae745f3640455513a9824c1d3a59e1be
# Parent  2904229ed97ec1d90a055ad86759f867cdc5296b
Fix incorrect handling of constant pool entries of type CONSTANT_NAMEANDTYPE, CONSTANT_METHODHANDLE, CONSTANT_DYNAMIC and CONSTANT_INVOKEDYNAMIC.

diff --git a/src/org/openjdk/asmtools/jdis/ConstantPool.java b/src/org/openjdk/asmtools/jdis/ConstantPool.java
--- a/src/org/openjdk/asmtools/jdis/ConstantPool.java
+++ b/src/org/openjdk/asmtools/jdis/ConstantPool.java
@@ -500,8 +500,9 @@
      * CPX2
      *
      * Constant entries that contain two constant-pool indices. Usually, this includes:
-     * CONSTANT_FIELD CONSTANT_METHOD CONSTANT_INTERFACEMETHOD CONSTANT_NAMEANDTYPE
-     * CONSTANT_METHODHANDLE CONSTANT_DYNAMIC CONSTANT_INVOKEDYNAMIC
+     * CONSTANT_NAMEANDTYPE CONSTANT_METHODHANDLE CONSTANT_DYNAMIC CONSTANT_INVOKEDYNAMIC
+     *
+     * For constant entries referencing class members use CPX2_ClassMember instead.
      *
      */
     class CPX2 extends Constant {
@@ -600,6 +601,23 @@
         }
     }
 
+    /**
+     * CPX2_ClassMember
+     *
+     * Specialized subclass of CPX2 class for constant entries that contain two constant-pool indices
+     * with first index pointing to the constant pool entry of type CONSTANT_CLASS.
+     *
+     * Usually, this includes: CONSTANT_FIELD CONSTANT_METHOD CONSTANT_INTERFACEMETHOD
+     *
+     */
+    class CPX2_ClassMember extends CPX2 {
+
+        CPX2_ClassMember(TAG tagval, int cpx1, int cpx2) {
+            super(tagval, cpx1, cpx2);
+        }
+
+    }
+
     /* -------------------------------------------------------- */
     /* ConstantPool Fields */
     /**
@@ -674,6 +692,8 @@
                 case CONSTANT_FIELD:
                 case CONSTANT_METHOD:
                 case CONSTANT_INTERFACEMETHOD:
+                    pool.add(i, new CPX2_ClassMember(tagobj, in.readUnsignedShort(), in.readUnsignedShort()));
+                    break;
                 case CONSTANT_NAMEANDTYPE:
                 case CONSTANT_DYNAMIC:
                 case CONSTANT_INVOKEDYNAMIC:
@@ -845,13 +865,13 @@
      *
      * getClassName
      *
-     * Safely gets a Java class name from a ConstantClass from a CPX2 constant pool
+     * Safely gets a Java class name from a ConstantClass from a CPX2_ClassMember constant pool
      * object. (eg. Method/Field/Interface Ref)
      *
      * Returns either the Java class name, or a CP index reference string.
      *
      */
-    public String getClassName(CPX2 classConst) {
+    public String getClassName(CPX2_ClassMember classConst) {
         return _getClassName(classConst.value1);
     }
 
@@ -998,17 +1018,10 @@
         if (cns == null) {
             return "#" + cpx;
         }
-        switch (cns.tag) {
-            case CONSTANT_METHODHANDLE:
-            case CONSTANT_DYNAMIC:
-            case CONSTANT_INVOKEDYNAMIC:
-            case CONSTANT_METHOD:
-            case CONSTANT_INTERFACEMETHOD:
-            case CONSTANT_FIELD: {
-                CPX2 cns2 = (CPX2) cns;
-                if (cns2.value1 == cd.this_cpx) {
-                    cpx = cns2.value2;
-                }
+        if (cns instanceof CPX2_ClassMember) {
+            CPX2_ClassMember cns2 = (CPX2_ClassMember) cns;
+            if (cns2.value1 == cd.this_cpx) {
+                cpx = cns2.value2;
             }
         }
         return cns.tag.tagname + " " + StringValue(cpx);


More information about the code-tools-dev mailing list