Menu

#767 A misjudgment exception occurs while preverifying

v6.0
closed-works-for-me
Medium
2019-12-05
2019-10-12
Mr Yang
No

I encountered a problem when using Proguard(version 6.0.3) in my android project.
Below is the stack of exceptions:(I am sorry that some code info of our program was replaceed by xxx/a/)

Ignoring unused library classes...
  Original number of library classes: 6448
  Final number of library classes:    2187
Printing kept classes, fields, and methods...
Inlining subroutines...
Obfuscating...
Printing mapping to [/root/workspace/xxx/build/outputs/mapping/xxx/release/mapping.txt]...
Preverifying...
Unexpected error while performing partial evaluation:
  Class       = [xxx/a/b]
  Method      = [a(Ljava/lang/String;)V]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes))
Unexpected error while preverifying:

First of all,i guess that there must be something wrong with my compilation(such as modify our program classes) or a bug of proguard in obfuscating process(we had turned off optimization )。So i tried to modify proguard and add a preverifying process before obfuscating ,below is the changes:

public void execute() throws IOException
{
    ...
    readInput();
    ...
    if (configuration.addConfigurationDebugging)
    {
        addConfigurationLogging();
    }
    //**********added*************
    if (configuration.preverify)
    {
        preverify();
    }

    if (configuration.printSeeds != null)
    {
        printSeeds();
    }
   ...
    if (configuration.preverify)
    {
        preverify();
    }
    ....
}

And i ran compilation again and the exceptiion(stack is same as before) still occured.

Ignoring unused library classes...
  Original number of library classes: 6448
  Final number of library classes:    2187
Preverifying...
Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes)
0   aload_1 v1              popCount 0  pushCount 1 inst lenth 1
1   ldc #214                popCount 0  pushCount 1 inst lenth 2
3   invokestatic #49        popCount 2  pushCount 0 inst lenth 3
6   aload_0 v0              popCount 0  pushCount 1 inst lenth 1
7   aload_1 v1              popCount 0  pushCount 1 inst lenth 1
8   putfield #75            popCount 2  pushCount 0 inst lenth 3
11  aload_0 v0              popCount 0  pushCount 1 inst lenth 1
12  getfield #19            popCount 1  pushCount 1 inst lenth 3
15  checkcast #29           popCount 1  pushCount 1 inst lenth 3
18  dup                     popCount 1  pushCount 2 inst lenth 1
19  ifnull +18              popCount 1  pushCount 0 inst lenth 3
22  invokevirtual #32       popCount 1  pushCount 1 inst lenth 3
25  dup                     popCount 1  pushCount 2 inst lenth 1
26  ifnull +11              popCount 1  pushCount 0 inst lenth 3
29  invokeinterface #217, 256   popCount 1  pushCount 0 inst lenth 5
34  goto +4                 popCount 0  pushCount 0 inst lenth 3
37  pop                     popCount 1  pushCount 0 inst lenth 1
38  aload_0 v0              popCount 0  pushCount 1 inst lenth 1
39  iconst_0                popCount 0  pushCount 1 inst lenth 1
40  putfield #83            popCount 2  pushCount 0 inst lenth 3
43  return                  popCount 0  pushCount 0 inst lenth 1

Unexpected error while performing partial evaluation:
  Class       = [xxx/a/b]
  Method      = [restore(Ljava/lang/String;)V]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes))
Unexpected error while preverifying:

Note:I have changed code of proguard and print the bytecode of method while exception occured
According to the log,we could find the location where the exception throwed:

/**
 * Returns the most specific common superclass or interface of the given
 * classes.
 * @param class1     the first class.
 * @param class2     the second class.
 * @param interfaces specifies whether to look for a superclass or for an
 *                   interface.
 * @return the common class.
 */
private Clazz findCommonClass(Clazz   class1,
                              Clazz   class2,
                              boolean interfaces)
{
    // Collect the superclasses or the interfaces of this class.
    ...
    if (commonClass == null)
    {
        throw new IllegalArgumentException("Can't find common super class of ["+
                                           class1.getName() +"] (with "+superClasses1Count +" known super classes) and ["+
                                           class2.getName()+"] (with "+superClasses2Count+" known super classes)");
    }
    ...
    return commonClass;
}

I was shocked that why preverifier goes to find common super class bettwen xxx/a/c and java/util/List
So, there should be a problem with the bytecode(location:xxx/a/b.restore) before proguard and i found the class.Here is the bytecode(before as a program input) of method 'xxx/a/b.restore':

// access flags 0x11
  public final restore(Ljava/lang/String;)V
    // annotable parameter count: 1 (invisible)
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 1
    LDC "requestId"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 105 L1
    ALOAD 0
    ALOAD 1
    PUTFIELD xxx/a/b.requestSessionId : Ljava/lang/String;
   L2
    LINENUMBER 106 L2
    ALOAD 0
    GETFIELD xxx/a/b.mData : Ljava/lang/Object;
    CHECKCAST xxx/a/c
    DUP
    IFNULL L3
    INVOKEVIRTUAL xxx/a/c.getAwemeList ()Ljava/util/List;
    DUP
    IFNULL L3
    INVOKEINTERFACE java/util/List.clear ()V (itf)
    GOTO L4
   L3
   FRAME SAME1 java/lang/Object
    POP
   L4
    LINENUMBER 107 L4
   FRAME SAME
    ALOAD 0
    ICONST_0
    PUTFIELD xxx/a/b.mCursor : I
   L5
    LINENUMBER 108 L5
    RETURN
   L6
    LOCALVARIABLE this Lxxx/a/b; L0 L6 0
    LOCALVARIABLE requestId Ljava/lang/String; L0 L6 1
    MAXSTACK = 2
    MAXLOCALS = 2

The source code was writtern by koltin and much like below:

package xxx.a
class b:d<c>(){
    ...
    104  fun restore(requestId: String) {
    105   requestSessionId = requestId
    106    mData?.awemeList?.clear()
    107    mCursor = 0
    108  }
    ...
}

And then,i had tried to find something bad within the bytecode but everything is legall.
And then,i had tried to find something different bytecode bettwen the xxx/a/b.restore and the outcome of kotlin compilation but it is no different(Around java/util/List),Below is the outcome bytecode of kotlin compilation:

  // access flags 0x11
  public final restore(Ljava/lang/String;)V
    // annotable parameter count: 1 (visible)
    // annotable parameter count: 1 (invisible)
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 1
    LDC "requestId"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 105 L1
    ALOAD 0
    ALOAD 1
    PUTFIELD xxx/a/b.requestSessionId : Ljava/lang/String;
   L2
    LINENUMBER 106 L2
    ALOAD 0
    GETFIELD xxx/a/b.mData : Ljava/lang/Object;
    CHECKCAST xxx/a/c
    DUP
    IFNULL L3
    INVOKEVIRTUAL xxx/a/c.getAwemeList ()Ljava/util/List;
    DUP
    IFNULL L3
    INVOKEINTERFACE java/util/List.clear ()V (itf)
    GOTO L4
   L3
    POP
   L4
   L5
    LINENUMBER 107 L5
    ALOAD 0
    ICONST_0
    PUTFIELD xxx/a/b.mCursor : I
   L6
    LINENUMBER 108 L6
    RETURN
   L7
    LOCALVARIABLE this Lxxx/a/b; L0 L7 0
    LOCALVARIABLE requestId Ljava/lang/String; L0 L7 1
    MAXSTACK = 2
    MAXLOCALS = 2

diff
And then,i guessed It's a bug in the verification process .I tried to turned off verification and ran on my app and found tha the app was working fine,with no crash.
So,i think it is a bug of proguard。
Note:I have tried the latest version(6.2.0) and it still no work.

Discussion

  • Mr Yang

    Mr Yang - 2019-10-12
     

    Last edit: Mr Yang 2019-10-12
  • Eric Lafortune

    Eric Lafortune - 2019-10-22

    Thank you for your extensive research. This error typically occurs if ProGuard doesn't have the complete class hierarchy of all classes that are processed. Have you suppressed any warnings with -dontwarn or -ignorewarnings? Can you run ProGuard without these settings? If you get warnings about missing classes, can you add their jars to the input?

    See https://www.guardsquare.com/en/products/proguard/manual/troubleshooting#superclass

     
    👍
    1
  • Eric Lafortune

    Eric Lafortune - 2019-10-22
    • status: open --> open-works-for-me
     
  • T. Neidhart

    T. Neidhart - 2019-12-05
    • status: open-works-for-me --> closed-works-for-me
     
  • T. Neidhart

    T. Neidhart - 2019-12-05

    Closing this issue.
    Please also note that when using ProGuard for an android project, there is no need for preverification, so you should add -dontpreverify in your configuration which probably also avoid the problem.

     

Log in to post a comment.