JesusFreke / smali

smali/baksmali
6.29k stars 1.07k forks source link

Qualified generics breaks .param identification #803

Closed RenateUSB closed 3 years ago

RenateUSB commented 3 years ago
# Synopsis: Qualified generics (List<Object>) breaks .param identification.
# bogus3() has no p4
# "object_cats" can be found stuffed in classes.dex
# Using Apktool v2.5.0

# public void bogus1(int apes, long bats, double double_cats, int dogs) {}

.method public bogus1(IJDI)V
    .locals 0
    .param p1, "apes"    # I
    .param p2, "bats"    # J
    .param p4, "double_cats"    # D
    .param p6, "dogs"    # I

# public void bogus2(int apes, long bats, List generic_cats, int dogs) {}

.method public bogus2(IJLjava/util/List;I)V
    .locals 0
    .param p1, "apes"    # I
    .param p2, "bats"    # J
    .param p4, "generic_cats"    # Ljava/util/List;
    .param p5, "dogs"    # I

# public void bogus3(int apes, long bats, List<Object> object_cats, int dogs) {}

.method public bogus3(IJLjava/util/List;I)V
    .locals 0
    .param p1, "apes"    # I
    .param p2, "bats"    # J
    .param p5, "dogs"    # I
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(IJ",
            "Ljava/util/List",
            "<",
            "Ljava/lang/Object;",
            ">;I)V"
        }
    .end annotation

# C:\>findtext classes.dex object_cats
# 00007CE1  object_cats
JesusFreke commented 3 years ago

I assume you're referring to the lack of a .param for the object_cats parameter?

From a quick test, it looks like that information gets encoded in the dex file as a .local, not as a .param.

Blah.java:

import java.util.List;

public class Blah {
    public void bogus3(int apes, long bats, List<Object> object_cats, int dogs) {}
}

javac -source 8 -target 8 -g Blah.java dx --dex --output=blah.dex Blah.class baksmali d blah.dex -o blah

And the relevant bit in Blah.smali:

# virtual methods
.method public bogus3(IJLjava/util/List;I)V
    .registers 6
    .param p1, "apes"    # I
    .param p2, "bats"    # J
    .param p5, "dogs"    # I
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(IJ",
            "Ljava/util/List",
            "<",
            "Ljava/lang/Object;",
            ">;I)V"
        }
    .end annotation

    .prologue
    .line 4
    .local p4, "object_cats":Ljava/util/List;, "Ljava/util/List<Ljava/lang/Object;>;"
    return-void
.end method

And looking at the raw info in the dex:

baksmali dump blah.dex > blah.dump

                           |[1] debug_info_item
00027b: 04                 |  line_start = 4
00027c: 04                 |  parameters_size = 4
                           |  parameters:
00027d: 10                 |    string_id_item[15]: "apes"
00027e: 11                 |    string_id_item[16]: "bats"
00027f: 00                 |    string_id_item[NO_INDEX]
000280: 13                 |    string_id_item[18]: "dogs"
                           |  debug opcodes:
000281: 04                 |    DBG_START_LOCAL_EXTENDED
000282: 04                 |      register_num = v4
000283: 14                 |      name_idx = string_id_item[19]: "object_cats"
000284: 06                 |      type_idx = type_id_item[5]: Ljava/util/List;
000285: 0d                 |      sig_idx = string_id_item[12]: "Ljava/util/List<Ljava/lang/Object;>;"
000286: 07                 |    DBG_SET_PROLOGUE_END
000287: 0e                 |    address_diff = +0x0:0x0, line_diff = +0:4, 
000288: 00                 |    DBG_END_SEQUENCE

Which confirms that the object_cats parameter name is encoded as a local variable, instead of as a parameter in the dex file, so baksmali's representation correctly matches that in the dex file.

RenateUSB commented 3 years ago

Thank you very much. You've demonstrated that baksmali is doing its job correctly. Still, that is crazy stuff, that NO_INDEX just because it's List<Object> instead of List. I don't see what harm it would have done to have it in both .param and .local (if they really needed that extended info). I wonder if it's javac or dex doing that? (Feel free to close it if you like.)

JesusFreke commented 3 years ago

Yeah, I'm not sure. You could take a look at the .class file before it gets converted to a dex file, and see how the parameter names are represented there.

RenateUSB commented 3 years ago

I forgot that I did have a hacked together class dumper.

public void bogus2(int, long, List, int) Attr: Code 83 Attr: MethodParameters 17 Param apes Param bats Param generic_cats Param dogs

public void bogus3(int, long, List, int) Attr: Code 101 Attr: MethodParameters 17 Param apes Param bats Param object_cats Param dogs Attr: Signature 2 Sig (IJLjava/util/List<Ljava/lang/Object;>;I)V

So dex is quilty, by design or oversight.