Recaf icon indicating copy to clipboard operation
Recaf copied to clipboard

Incorrect method reassembly with reused variable indices

Open gotroc opened this issue 5 years ago • 5 comments

Experiencing an issue with modifying a specific method. Done plenty of other modifications in the same class, but only this method is causing trouble...

I'm editing this line from : int rounds = 4 + Game.random.nextInt(4); to int rounds = 6 + Game.random.nextInt(6);

by changing:

LINE B 2606
ICONST_4
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
ICONST_4
INVOKEVIRTUAL java/util/Random.nextInt(I)I

to

LINE B 2606
BIPUSH 6
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
BIPUSH 6
INVOKEVIRTUAL java/util/Random.nextInt(I)I

Note that no matter the modification I'm getting the same issue (if I change ICONST_4 to ICONST_5 for example).

Something I noticed is that before altering the method the "locals" panel show : image and after : image

And this smell familiar with the crash report I'm getting when running :

Thread[Thread-1,5,main]
com.badlogic.gdx.utils.GdxRuntimeException: java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    fi/bugbyte/spacehaven/world/Space.addField(II[[ILfi/bugbyte/spacehaven/world/elements/MultiElement;Lfi/bugbyte/spacehaven/starmap/StarMap$SectorResource;)V @103: iload
  Reason:
    Type '[[I' (current frame, locals[11]) is not assignable to integer
  Current Frame:
    bci: @103
    flags: { }
    locals: { 'fi/bugbyte/spacehaven/world/Space', integer, integer, '[[I', 'fi/bugbyte/spacehaven/world/elements/MultiElement', 'fi/bugbyte/spacehaven/starmap/StarMap$SectorResource', 'fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField', integer, integer, integer, integer, '[[I' }
    stack: { 'fi/bugbyte/spacehaven/world/Space', '[[I', '[[I', integer }
  Bytecode:
    0x0000000: bb00 3459 2ab4 0127 b704 803a 0610 06b2
    0x0000010: 0463 1006 b604 6860 3607 100e 3608 0336
    0x0000020: 0915 0915 07a2 004d 1bb2 0463 1508 0460
    0x0000030: b604 6860 1508 056c 6406 6436 0a1c b204
    0x0000040: 6315 0804 60b6 0468 6015 0805 6c64 0664
    0x0000050: 360b 2ab2 0463 05b6 0468 0660 b704 843a
    0x0000060: 0b2a 2d19 0b15 0a15 0bb7 0487 8409 01a7
    0x0000070: ffb2 0336 0915 092d bea2 0076 0336 0a15
    0x0000080: 0a2d 1509 32be a200 632d 1509 3215 0a2e
    0x0000090: 360b 150b 04a0 0046 150a 360c 1509 360d
    0x00000a0: 2a19 0415 0c15 0db7 048b 2ab4 017c b401
    0x00000b0: 7a15 0d32 150c 1100 ff4f 2a15 0c15 0db7
    0x00000c0: 048e 2a15 0c15 0db6 048f c000 363a 0e19
    0x00000d0: 0ec6 000a 1906 190e b604 922d 1509 3215
    0x00000e0: 0a03 4f84 0a01 a7ff 9984 0901 a7ff 8919
    0x00000f0: 062a b601 8f2a b601 92b6 0495 2ab4 0148
    0x0000100: 1906 b603 6319 06b6 0498 1905 b404 9936
    0x0000110: 09b2 03b1 1905 b403 a1b9 049d 0200 3a0a
    0x0000120: 1906 190a 1509 b604 a1b1               
  Stackmap Table:
    full_frame(@33,{Object[#2],Integer,Integer,Object[#383],Object[#975],Object[#99],Object[#52],Integer,Integer,Integer},{})
    same_frame_extended(@114)
    same_frame(@117)
    append_frame(@127,Integer)
    append_frame(@219,Integer)
    chop_frame(@233,1)
    chop_frame(@239,1)

com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:117)
fi.bugbyte.spacehaven.MainClass$3.run(MainClass.java:393)
java.lang.Thread.run(Thread.java:748)

Here is the class files :

classes.zip

Original method :

    private void addField(int x, int y, int[][] map, MultiElement a, StarMap.SectorResource ore) {
        int i;
        Asteroid.AsteroidField f = new Asteroid.AsteroidField(this.world);
        int rounds = 4 + Game.random.nextInt(4);
        int sx = 14;
        for (i = 0; i < rounds; ++i) {
            int px = x + Game.random.nextInt(sx + 1) - sx / 2 - 3;
            int py = y + Game.random.nextInt(sx + 1) - sx / 2 - 3;
            int[][] m = this.addAsteroid(Game.random.nextInt(2) + 3);
            this.add(map, m, px, py);
        }
        for (i = 0; i < map.length; ++i) {
            for (int j = 0; j < map[i].length; ++j) {
                int m = map[i][j];
                if (m == 1) {
                    int gx = j;
                    int gy = i;
                    this.addElement(a, gx, gy);
                    this.currentLightMap.lightMap[gy][gx] = 255;
                    this.addFog(gx, gy);
                    Asteroid ast = (Asteroid)this.get(gx, gy);
                    if (ast != null) {
                        f.addAsteroid(ast);
                    }
                }
                map[i][j] = 0;
            }
        }
        f.makeBoundingGrid(this.getSizeX(), this.getSizeY());
        this.fields.add(f);
        f.initField();
        int n = ore.howMuch;
        Production.Elementary o = SpaceHaven.library.getElementary(ore.elementId);
        f.setOre(o, n);
    }
DEFINE PRIVATE addField(I x, I y, [[I map, Lfi/bugbyte/spacehaven/world/elements/MultiElement; a, Lfi/bugbyte/spacehaven/starmap/StarMap$SectorResource; ore)V
A:
LINE A 2604
NEW fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField
DUP
ALOAD this
GETFIELD fi/bugbyte/spacehaven/world/Space.world Lfi/bugbyte/spacehaven/world/World;
INVOKESPECIAL fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField.<init>(Lfi/bugbyte/spacehaven/world/World;)V
ASTORE f
B:
LINE B 2606
ICONST_4
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
ICONST_4
INVOKEVIRTUAL java/util/Random.nextInt(I)I
IADD
ISTORE rounds
C:
LINE C 2607
BIPUSH 14
ISTORE sx
D:
LINE D 2609
ICONST_0
ISTORE i
E:
ILOAD i
ILOAD rounds
IF_ICMPGE K
F:
LINE F 2610
ILOAD x
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
ILOAD sx
ICONST_1
IADD
INVOKEVIRTUAL java/util/Random.nextInt(I)I
IADD
ILOAD sx
ICONST_2
IDIV
ISUB
ICONST_3
ISUB
ISTORE px
G:
LINE G 2611
ILOAD y
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
ILOAD sx
ICONST_1
IADD
INVOKEVIRTUAL java/util/Random.nextInt(I)I
IADD
ILOAD sx
ICONST_2
IDIV
ISUB
ICONST_3
ISUB
ISTORE py
H:
LINE H 2612
ALOAD this
GETSTATIC fi/bugbyte/framework/Game.random Ljava/util/Random;
ICONST_2
INVOKEVIRTUAL java/util/Random.nextInt(I)I
ICONST_3
IADD
INVOKESPECIAL fi/bugbyte/spacehaven/world/Space.addAsteroid(I)[[I
ASTORE m
I:
LINE I 2613
ALOAD this
ALOAD map
ALOAD m
ILOAD px
ILOAD py
INVOKESPECIAL fi/bugbyte/spacehaven/world/Space.add([[I[[III)V
J:
LINE J 2609
IINC i 1
GOTO E
K:
LINE K 2616
ICONST_0
ISTORE i
L:
ILOAD i
ALOAD map
ARRAYLENGTH
IF_ICMPGE AB
M:
LINE M 2617
ICONST_0
ISTORE j
N:
ILOAD j
ALOAD map
ILOAD i
AALOAD
ARRAYLENGTH
IF_ICMPGE AA
O:
LINE O 2618
ALOAD map
ILOAD i
AALOAD
ILOAD j
IALOAD
ISTORE m
P:
LINE P 2619
ILOAD m
ICONST_1
IF_ICMPNE Y
Q:
LINE Q 2620
ILOAD j
ISTORE gx
R:
LINE R 2621
ILOAD i
ISTORE gy
S:
LINE S 2622
ALOAD this
ALOAD a
ILOAD gx
ILOAD gy
INVOKESPECIAL fi/bugbyte/spacehaven/world/Space.addElement(Lfi/bugbyte/spacehaven/world/elements/MultiElement;II)V
T:
LINE T 2623
ALOAD this
GETFIELD fi/bugbyte/spacehaven/world/Space.currentLightMap Lfi/bugbyte/spacehaven/world/Light$LightMap;
GETFIELD fi/bugbyte/spacehaven/world/Light$LightMap.lightMap [[I
ILOAD gy
AALOAD
ILOAD gx
SIPUSH 255
IASTORE
U:
LINE U 2624
ALOAD this
ILOAD gx
ILOAD gy
INVOKESPECIAL fi/bugbyte/spacehaven/world/Space.addFog(II)V
V:
LINE V 2625
ALOAD this
ILOAD gx
ILOAD gy
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/Space.get(II)Lfi/bugbyte/spacehaven/world/elements/WorldElement;
CHECKCAST fi/bugbyte/spacehaven/world/elements/Asteroid
ASTORE ast
W:
LINE W 2626
ALOAD ast
IFNULL Y
X:
LINE X 2627
ALOAD f
ALOAD ast
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField.addAsteroid(Lfi/bugbyte/spacehaven/world/elements/Asteroid;)V
Y:
LINE Y 2629
ALOAD map
ILOAD i
AALOAD
ILOAD j
ICONST_0
IASTORE
Z:
LINE Z 2617
IINC j 1
GOTO N
AA:
LINE AA 2616
IINC i 1
GOTO L
AB:
LINE AB 2634
ALOAD f
ALOAD this
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/Space.getSizeX()I
ALOAD this
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/Space.getSizeY()I
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField.makeBoundingGrid(II)V
AC:
LINE AC 2635
ALOAD this
GETFIELD fi/bugbyte/spacehaven/world/Space.fields Lcom/badlogic/gdx/utils/Array;
ALOAD f
INVOKEVIRTUAL com/badlogic/gdx/utils/Array.add(Ljava/lang/Object;)V
AD:
LINE AD 2636
ALOAD f
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField.initField()V
AE:
LINE AE 2638
ALOAD ore
GETFIELD fi/bugbyte/spacehaven/starmap/StarMap$SectorResource.howMuch I
ISTORE n
AF:
LINE AF 2639
GETSTATIC fi/bugbyte/spacehaven/SpaceHaven.library Lfi/bugbyte/spacehaven/ElementLibrary;
ALOAD ore
GETFIELD fi/bugbyte/spacehaven/starmap/StarMap$SectorResource.elementId I
INVOKEINTERFACE fi/bugbyte/spacehaven/ElementLibrary.getElementary(I)Lfi/bugbyte/spacehaven/stuff/Production$Elementary;
ASTORE o
AG:
LINE AG 2641
ALOAD f
ALOAD o
ILOAD n
INVOKEVIRTUAL fi/bugbyte/spacehaven/world/elements/Asteroid$AsteroidField.setOre(Lfi/bugbyte/spacehaven/stuff/Production$Elementary;I)V
AH:
LINE AH 2642
RETURN
AI:

gotroc avatar Oct 22 '20 11:10 gotroc

Please try disabling Use existing data in assembler's config and see if that helps.

xxDark avatar Oct 22 '20 13:10 xxDark

Yep disabling use existing data works, and in the meantime I noticed a few other places where this worked. Does enabling the option has any benefit or is it just a performance thing ?

gotroc avatar Oct 23 '20 19:10 gotroc

This option allows you to see local variable names, that's all iirc.

xxDark avatar Oct 23 '20 19:10 xxDark

Right so currently the assembler has no context of scoped variables. The following java code shows a use case:

int a = 0;
{
   int b = 2;
   a+=b;
}
{
   int b = 10;
   a += b;
}

There would be two declarations of b here, but Recaf's assembler so far doesn't understand scopes. Instead it has some tricks to get around this, but they dont cover all cases. Like dark mentioned, this can be worked around by fiddling with the options until a proper fix is implemented.

Col-E avatar Oct 24 '20 17:10 Col-E

While not properly fixed a9c2bac3d34fc347d7e8f4347950880c6e461f07 should allow editing of this method. It will flatten some variables together though as long as they share the same type.

Col-E avatar Dec 11 '20 08:12 Col-E