Storyyeller / Krakatau

Java decompiler, assembler, and disassembler
GNU General Public License v3.0
1.95k stars 220 forks source link

Issues with ints and booleans and comparision #95

Closed Janmm14 closed 8 years ago

Janmm14 commented 8 years ago

As booleans are basically ints in the stack, there are some issues noticed by me where krakatau puts out code like if (bool >= 0). A possible solution would be to add an inline if: if ((bool?:1:0) >= 0) (if that decompiled code above is even correct at all) I additionally noticed this:

System.currentTimeMillis() != ((Long)some.class.someMap.get((Object)a0.someUUIDreturningMethod())).longValue();

Which looks to be wrong (also as other decompilers show a subtraction).

Here is the bytecode where I found these two issues (sorry, anonymized)

.method public a : (Lsome/class2;)Z
    .code stack 6 locals 4 
L0:     getstatic Field some/class alwaysZero I 
L3:     istore_3 
L4:     aload_0 
L5:     getfield Field some/class someMap Ljava/util/Map; 
L8:     aload_1 
L9:     invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L14:    invokeinterface InterfaceMethod java/util/Map containsKey (Ljava/lang/Object;)Z 2 
L19:    iload_3 
L20:    ifne L61 
L23:    ifne L46 
L26:    aload_0 
L27:    getfield Field some/class someMap Ljava/util/Map; 
L30:    aload_1 
L31:    invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L36:    lconst_0 
L37:    invokestatic Method java/lang/Long valueOf (J)Ljava/lang/Long; 
L40:    invokeinterface InterfaceMethod java/util/Map put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 3 
L45:    pop 

        .stack append Top Integer 
L46:    aload_0 
L47:    getfield Field some/class someSet Ljava/util/Set; 
L50:    aload_1 
L51:    invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L56:    invokeinterface InterfaceMethod java/util/Set contains (Ljava/lang/Object;)Z 2 

        .stack stack_1 Integer 
L61:    iload_3 
L62:    ifne L226 
L65:    ifeq L201 
L68:    invokestatic Method java/lang/System currentTimeMillis ()J 
L71:    aload_0 
L72:    getfield Field some/class someMap Ljava/util/Map; 
L75:    aload_1 
L76:    invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L81:    invokeinterface InterfaceMethod java/util/Map get (Ljava/lang/Object;)Ljava/lang/Object; 2 
L86:    checkcast java/lang/Long 
L89:    invokevirtual Method java/lang/Long longValue ()J 
L92:    lcmp 
L93:    iload_3 
L94:    ifne L115 
L97:    ifge L106 
L100:   iconst_1 
L101:   istore_2 
L102:   iload_3 
L103:   ifeq L330 

        .stack same 
L106:   aload_1 
L107:   ldc_w 'iAmAString' 
L110:   invokeinterface InterfaceMethod some/class2 someMethod (Ljava/lang/String;)Z 2 

        .stack stack_1 Integer 
L115:   istore_2 
L116:   iload_2 
L117:   iload_3 
L118:   ifne L159 
L121:   ifeq L144 
L124:   aload_0 
L125:   getfield Field some/class someSet Ljava/util/Set; 
L128:   aload_1 
L129:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L134:   invokeinterface InterfaceMethod java/util/Set add (Ljava/lang/Object;)Z 2 
L139:   pop 
L140:   iload_3 
L141:   ifeq L160 

        .stack full 
            locals Object some/class Object some/class2 Integer Integer 
            stack 
        .end stack 
L144:   aload_0 
L145:   getfield Field some/class someSet Ljava/util/Set; 
L148:   aload_1 
L149:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L154:   invokeinterface InterfaceMethod java/util/Set remove (Ljava/lang/Object;)Z 2 

        .stack stack_1 Integer 
L159:   pop 

        .stack same 
L160:   aload_0 
L161:   getfield Field some/class someMap Ljava/util/Map; 
L164:   aload_1 
L165:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L170:   invokestatic Method java/lang/System currentTimeMillis ()J 
L173:   getstatic Field some/class random Ljava/util/Random; 
L176:   sipush 6374 
L179:   invokevirtual Method java/util/Random nextInt (I)I 
L182:   i2l 
L183:   ladd 
L184:   ldc2_w 5387L 
L187:   ladd 
L188:   invokestatic Method java/lang/Long valueOf (J)Ljava/lang/Long; 
L191:   invokeinterface InterfaceMethod java/util/Map put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 3 
L196:   pop 
L197:   iload_3 
L198:   ifeq L330 

        .stack full 
            locals Object some/class Object some/class2 Top Integer 
            stack 
        .end stack 
L201:   invokestatic Method java/lang/System currentTimeMillis ()J 
L204:   aload_0 
L205:   getfield Field some/class someMap Ljava/util/Map; 
L208:   aload_1 
L209:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L214:   invokeinterface InterfaceMethod java/util/Map get (Ljava/lang/Object;)Ljava/lang/Object; 2 
L219:   checkcast java/lang/Long 
L222:   invokevirtual Method java/lang/Long longValue ()J 
L225:   lcmp 

        .stack stack_1 Integer 
L226:   iload_3 
L227:   ifne L248 
L230:   ifge L239 
L233:   iconst_0 
L234:   istore_2 
L235:   iload_3 
L236:   ifeq L330 

        .stack same 
L239:   aload_1 
L240:   ldc_w 'iAmAString' 
L243:   invokeinterface InterfaceMethod some/class2 someMethod (Ljava/lang/String;)Z 2 

        .stack stack_1 Integer 
L248:   istore_2 
L249:   iload_2 
L250:   iload_3 
L251:   ifne L292 
L254:   ifeq L277 
L257:   aload_0 
L258:   getfield Field some/class someSet Ljava/util/Set; 
L261:   aload_1 
L262:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L267:   invokeinterface InterfaceMethod java/util/Set add (Ljava/lang/Object;)Z 2 
L272:   pop 
L273:   iload_3 
L274:   ifeq L293 

        .stack full 
            locals Object some/class Object some/class2 Integer Integer 
            stack 
        .end stack 
L277:   aload_0 
L278:   getfield Field some/class someSet Ljava/util/Set; 
L281:   aload_1 
L282:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L287:   invokeinterface InterfaceMethod java/util/Set remove (Ljava/lang/Object;)Z 2 

        .stack stack_1 Integer 
L292:   pop 

        .stack same 
L293:   aload_0 
L294:   getfield Field some/class someMap Ljava/util/Map; 
L297:   aload_1 
L298:   invokeinterface InterfaceMethod some/class2 someUUIDreturningMethod ()Ljava/util/UUID; 1 
L303:   invokestatic Method java/lang/System currentTimeMillis ()J 
L306:   getstatic Field some/class random Ljava/util/Random; 
L309:   sipush 6374 
L312:   invokevirtual Method java/util/Random nextInt (I)I 
L315:   i2l 
L316:   ladd 
L317:   ldc2_w 5387L 
L320:   ladd 
L321:   invokestatic Method java/lang/Long valueOf (J)Ljava/lang/Long; 
L324:   invokeinterface InterfaceMethod java/util/Map put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 3 
L329:   pop 

        .stack same 
L330:   iload_2 
L331:   ireturn 
L332:   
    .end code 
.end method 
Storyyeller commented 8 years ago

Krakatau already does the bool?:1:0 thing. Unfortunately, it is not possible to fix every case.

Also, it's not clear to me what the problem is in the second example you listed. What do you want it to do instead?

Janmm14 commented 8 years ago

@Storyyeller It just looks wrong to have a != there for the code as System.currentTimeMillis() is very likely to differ from the value of the map, but it could differ in both directions which one normally doesn't want to check. Also I'm not that familiar with bytecode to check it out myself.

Storyyeller commented 8 years ago

As far as I can tell from the bytecode, != is correct here. Blame the people who wrote the code.

Janmm14 commented 8 years ago

Okay, thanks for the clarification. For the first issue it stays that I have to manually convert ints and booleans :/

Storyyeller commented 8 years ago

If they aren't converted automatically for whatever reason, then yes.