Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[core] RERUN_SSA_TRANSFORM generates broken or incorrect code in most cases #2236

Closed
pubiqq opened this issue Aug 1, 2024 · 3 comments
Closed
Assignees
Labels
bug Core Issues in jadx-core module regression
Milestone

Comments

@pubiqq
Copy link
Contributor

pubiqq commented Aug 1, 2024

Issue details

This usually happens with a code like this:

0x0005: NEW_INSTANCE (r0)
0x0010: INVOKE (r0, ...) <init>
0x0020: IPUT (r0, ...)
0x0025: MOVE (r10) = (r0)
0x0030: CONST (r0) = (...)
0x0040: APUT (r0, ...)
0x0050: INVOKE (...) = (r10, ...)
0x0060: CONST (r0) = (...)
0x0070: APUT (r0, ...)
0x0080: INVOKE (...) = (r10, ...)

After some transformations, the code can take the following form:

Step ConstructorVisitor, after visiting methods but before SSATransform#rerun

0x0010: CONSTRUCTOR (r0v0) = (...)
0x0020: IPUT (r0v0, ...)
0x0030: CONST (r0v1) = (...)
0x0040: APUT (r0v1, ...)
0x0050: INVOKE (...) = (r0v0, ...)
0x0060: CONST (r0v2) = (...)
0x0070: APUT (r0v2, ...)
0x0080: INVOKE (...) = (r0v0, ...)

And then, SSATransform#rerun calls SSATransform#resetSSAVars and it removes variables' versions, which makes the code incorrect:

Step ConstructorVisitor, after SSATransform#resetSSAVars

0x0010: CONSTRUCTOR (r0) = (...)
0x0020: IPUT (r0)
0x0030: CONST (r0) = (...)
0x0040: APUT (r0, ...)
0x0050: INVOKE (...) = (r0, ...)  // info that `r0v0` was used here (not `r0v1`) has been lost
0x0060: CONST (r0) = (...)
0x0070: APUT (r0, ...)
0x0080: INVOKE (...) = (r0, ...)  // info that `r0v0` was used here (not `r0v1` or `r0v2`) has been lost

Step ConstructorVisitor, after SSATransform#process

0x0010: CONSTRUCTOR (r0v0) = (...)
0x0020: IPUT (r0v0)
0x0030: CONST (r0v1) = (...)
0x0040: APUT (r0v1, ...)
0x0050: INVOKE (...) = (r0v1, ...)  // should be r0v0
0x0060: CONST (r0v2) = (...)
0x0070: APUT (r0v2, ...)
0x0080: INVOKE (...) = (r0v2, ...)  // should be r0v0

Provide sample and class/method full name

smali code

.method public onCreateView(Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Landroid/os/Bundle;)Landroid/view/View;
    .locals 22
    .param p1, "layoutInflater"    # Landroid/view/LayoutInflater;
    .param p2, "viewGroup"    # Landroid/view/ViewGroup;
    .param p3, "bundle"    # Landroid/os/Bundle;

    .local p0, "this":Lcom/google/android/material/datepicker/MaterialCalendar;, "Lcom/google/android/material/datepicker/MaterialCalendar<TS;>;"
    move-object/from16 v6, p0

    invoke-static {}, Lcom/google/android/material/datepicker/MaterialCalendar;->$jacocoInit()[Z

    move-result-object v7

    .line 147
    new-instance v0, Landroid/view/ContextThemeWrapper;

    invoke-virtual/range {p0 .. p0}, Lcom/google/android/material/datepicker/MaterialCalendar;->getContext()Landroid/content/Context;

    move-result-object v1

    iget v2, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->themeResId:I

    invoke-direct {v0, v1, v2}, Landroid/view/ContextThemeWrapper;-><init>(Landroid/content/Context;I)V

    const/16 v1, 0x19

    const/4 v8, 0x1

    aput-boolean v8, v7, v1

    move-object v15, v0

    .line 148
    .local v15, "themedContext":Landroid/view/ContextThemeWrapper;
    new-instance v0, Lcom/google/android/material/datepicker/CalendarStyle;

    invoke-direct {v0, v15}, Lcom/google/android/material/datepicker/CalendarStyle;-><init>(Landroid/content/Context;)V

    iput-object v0, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->calendarStyle:Lcom/google/android/material/datepicker/CalendarStyle;

    const/16 v0, 0x1a

    aput-boolean v8, v7, v0

    .line 149
    move-object/from16 v14, p1

    invoke-virtual {v14, v15}, Landroid/view/LayoutInflater;->cloneInContext(Landroid/content/Context;)Landroid/view/LayoutInflater;

    move-result-object v13

    .local v13, "themedInflater":Landroid/view/LayoutInflater;
    const/16 v0, 0x1b

    aput-boolean v8, v7, v0

    .line 151
    iget-object v0, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->calendarConstraints:Lcom/google/android/material/datepicker/CalendarConstraints;

    invoke-virtual {v0}, Lcom/google/android/material/datepicker/CalendarConstraints;->getStart()Lcom/google/android/material/datepicker/Month;

    move-result-object v12

    .local v12, "earliestMonth":Lcom/google/android/material/datepicker/Month;
    const/16 v0, 0x1c

    aput-boolean v8, v7, v0

    .line 155
    invoke-static {v15}, Lcom/google/android/material/datepicker/MaterialDatePicker;->isFullscreen(Landroid/content/Context;)Z

    move-result v0

    if-eqz v0, :cond_0

    .line 156
    sget v0, Lcom/google/android/material/R$layout;->mtrl_calendar_vertical:I

    .line 157
    .local v0, "layout":I
    const/4 v1, 0x1

    .local v1, "orientation":I
    const/16 v2, 0x1d

    aput-boolean v8, v7, v2

    move v11, v0

    move/from16 v16, v1

    goto :goto_0

    .line 159
    .end local v0    # "layout":I
    .end local v1    # "orientation":I
    :cond_0
    sget v0, Lcom/google/android/material/R$layout;->mtrl_calendar_horizontal:I

    .line 160
    .restart local v0    # "layout":I
    const/4 v1, 0x0

    .restart local v1    # "orientation":I
    const/16 v2, 0x1e

    aput-boolean v8, v7, v2

    move v11, v0

    move/from16 v16, v1

    .line 163
    .end local v0    # "layout":I
    .end local v1    # "orientation":I
    .local v11, "layout":I
    .local v16, "orientation":I
    :goto_0
    const/4 v10, 0x0

    move-object/from16 v9, p2

    invoke-virtual {v13, v11, v9, v10}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;

    move-result-object v5

    .local v5, "root":Landroid/view/View;
    const/16 v0, 0x1f

    aput-boolean v8, v7, v0

    .line 164
    invoke-virtual/range {p0 .. p0}, Lcom/google/android/material/datepicker/MaterialCalendar;->requireContext()Landroid/content/Context;

    move-result-object v0

    invoke-static {v0}, Lcom/google/android/material/datepicker/MaterialCalendar;->getDialogPickerHeight(Landroid/content/Context;)I

    move-result v0

    invoke-virtual {v5, v0}, Landroid/view/View;->setMinimumHeight(I)V

    const/16 v0, 0x20

    aput-boolean v8, v7, v0

    .line 165
    sget v0, Lcom/google/android/material/R$id;->mtrl_calendar_days_of_week:I

    invoke-virtual {v5, v0}, Landroid/view/View;->findViewById(I)Landroid/view/View;

    move-result-object v0

    move-object v4, v0

    check-cast v4, Landroid/widget/GridView;

    .local v4, "daysHeader":Landroid/widget/GridView;
    const/16 v0, 0x21

    aput-boolean v8, v7, v0

    .line 166
    new-instance v0, Lcom/google/android/material/datepicker/MaterialCalendar$1;

    invoke-direct {v0, v6}, Lcom/google/android/material/datepicker/MaterialCalendar$1;-><init>(Lcom/google/android/material/datepicker/MaterialCalendar;)V

    invoke-static {v4, v0}, Landroidx/core/view/ViewCompat;->setAccessibilityDelegate(Landroid/view/View;Landroidx/core/view/AccessibilityDelegateCompat;)V

    const/16 v0, 0x22

    aput-boolean v8, v7, v0

    .line 177
    iget-object v0, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->calendarConstraints:Lcom/google/android/material/datepicker/CalendarConstraints;

    invoke-virtual {v0}, Lcom/google/android/material/datepicker/CalendarConstraints;->getFirstDayOfWeek()I

    move-result v3

    .line 178
    .local v3, "firstDayOfWeek":I
    const/16 v0, 0x23

    aput-boolean v8, v7, v0

    .line 179
    new-instance v0, Lcom/google/android/material/datepicker/DaysOfWeekAdapter;

    if-lez v3, :cond_1

    invoke-direct {v0, v3}, Lcom/google/android/material/datepicker/DaysOfWeekAdapter;-><init>(I)V

    const/16 v1, 0x24

    aput-boolean v8, v7, v1

    goto :goto_1

    :cond_1
    invoke-direct {v0}, Lcom/google/android/material/datepicker/DaysOfWeekAdapter;-><init>()V

    const/16 v1, 0x25

    aput-boolean v8, v7, v1

    .line 178
    :goto_1
    invoke-virtual {v4, v0}, Landroid/widget/GridView;->setAdapter(Landroid/widget/ListAdapter;)V

    const/16 v0, 0x26

    aput-boolean v8, v7, v0

    .line 180
    iget v0, v12, Lcom/google/android/material/datepicker/Month;->daysInWeek:I

    invoke-virtual {v4, v0}, Landroid/widget/GridView;->setNumColumns(I)V

    const/16 v0, 0x27

    aput-boolean v8, v7, v0

    .line 181
    invoke-virtual {v4, v10}, Landroid/widget/GridView;->setEnabled(Z)V

    const/16 v0, 0x28

    aput-boolean v8, v7, v0

    .line 183
    sget v0, Lcom/google/android/material/R$id;->mtrl_calendar_months:I

    invoke-virtual {v5, v0}, Landroid/view/View;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroidx/recyclerview/widget/RecyclerView;

    iput-object v0, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    .line 185
    new-instance v17, Lcom/google/android/material/datepicker/MaterialCalendar$2;

    const/16 v0, 0x29

    aput-boolean v8, v7, v0

    .line 186
    invoke-virtual/range {p0 .. p0}, Lcom/google/android/material/datepicker/MaterialCalendar;->getContext()Landroid/content/Context;

    move-result-object v2

    const/16 v18, 0x0

    move-object/from16 v0, v17

    move-object/from16 v1, p0

    move/from16 v19, v3

    .end local v3    # "firstDayOfWeek":I
    .local v19, "firstDayOfWeek":I
    move/from16 v3, v16

    move-object/from16 v20, v4

    .end local v4    # "daysHeader":Landroid/widget/GridView;
    .local v20, "daysHeader":Landroid/widget/GridView;
    move/from16 v4, v18

    move-object/from16 v21, v5

    .end local v5    # "root":Landroid/view/View;
    .local v21, "root":Landroid/view/View;
    move/from16 v5, v16

    invoke-direct/range {v0 .. v5}, Lcom/google/android/material/datepicker/MaterialCalendar$2;-><init>(Lcom/google/android/material/datepicker/MaterialCalendar;Landroid/content/Context;IZI)V

    const/16 v0, 0x2a

    aput-boolean v8, v7, v0

    move-object/from16 v0, v17

    .line 198
    .local v0, "layoutManager":Lcom/google/android/material/datepicker/SmoothCalendarLayoutManager;
    iget-object v1, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    invoke-virtual {v1, v0}, Landroidx/recyclerview/widget/RecyclerView;->setLayoutManager(Landroidx/recyclerview/widget/RecyclerView$LayoutManager;)V

    const/16 v1, 0x2b

    aput-boolean v8, v7, v1

    .line 199
    iget-object v1, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    sget-object v2, Lcom/google/android/material/datepicker/MaterialCalendar;->MONTHS_VIEW_GROUP_TAG:Ljava/lang/Object;

    invoke-virtual {v1, v2}, Landroidx/recyclerview/widget/RecyclerView;->setTag(Ljava/lang/Object;)V

    const/16 v1, 0x2c

    aput-boolean v8, v7, v1

    .line 201
    new-instance v1, Lcom/google/android/material/datepicker/MonthsPagerAdapter;

    iget-object v2, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->dateSelector:Lcom/google/android/material/datepicker/DateSelector;

    iget-object v3, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->calendarConstraints:Lcom/google/android/material/datepicker/CalendarConstraints;

    iget-object v4, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->dayViewDecorator:Lcom/google/android/material/datepicker/DayViewDecorator;

    new-instance v5, Lcom/google/android/material/datepicker/MaterialCalendar$3;

    invoke-direct {v5, v6}, Lcom/google/android/material/datepicker/MaterialCalendar$3;-><init>(Lcom/google/android/material/datepicker/MaterialCalendar;)V

    move-object v9, v1

    move-object v10, v15

    move/from16 v17, v11

    .end local v11    # "layout":I
    .local v17, "layout":I
    move-object v11, v2

    move-object v2, v12

    .end local v12    # "earliestMonth":Lcom/google/android/material/datepicker/Month;
    .local v2, "earliestMonth":Lcom/google/android/material/datepicker/Month;
    move-object v12, v3

    move-object v3, v13

    .end local v13    # "themedInflater":Landroid/view/LayoutInflater;
    .local v3, "themedInflater":Landroid/view/LayoutInflater;
    move-object v13, v4

    move-object v14, v5

    invoke-direct/range {v9 .. v14}, Lcom/google/android/material/datepicker/MonthsPagerAdapter;-><init>(Landroid/content/Context;Lcom/google/android/material/datepicker/DateSelector;Lcom/google/android/material/datepicker/CalendarConstraints;Lcom/google/android/material/datepicker/DayViewDecorator;Lcom/google/android/material/datepicker/MaterialCalendar$OnDayClickListener;)V

    const/16 v4, 0x2d

    aput-boolean v8, v7, v4

    .line 224
    .local v1, "monthsPagerAdapter":Lcom/google/android/material/datepicker/MonthsPagerAdapter;
    iget-object v4, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    invoke-virtual {v4, v1}, Landroidx/recyclerview/widget/RecyclerView;->setAdapter(Landroidx/recyclerview/widget/RecyclerView$Adapter;)V

    .line 226
    const/16 v4, 0x2e

    aput-boolean v8, v7, v4

    .line 227
    invoke-virtual {v15}, Landroid/view/ContextThemeWrapper;->getResources()Landroid/content/res/Resources;

    move-result-object v4

    sget v5, Lcom/google/android/material/R$integer;->mtrl_calendar_year_selector_span:I

    invoke-virtual {v4, v5}, Landroid/content/res/Resources;->getInteger(I)I

    move-result v4

    .local v4, "columns":I
    const/16 v5, 0x2f

    aput-boolean v8, v7, v5

    .line 228
    sget v5, Lcom/google/android/material/R$id;->mtrl_calendar_year_selector_frame:I

    move-object/from16 v9, v21

    .end local v21    # "root":Landroid/view/View;
    .local v9, "root":Landroid/view/View;
    invoke-virtual {v9, v5}, Landroid/view/View;->findViewById(I)Landroid/view/View;

    move-result-object v5

    check-cast v5, Landroidx/recyclerview/widget/RecyclerView;

    iput-object v5, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->yearSelector:Landroidx/recyclerview/widget/RecyclerView;

    .line 229
    if-nez v5, :cond_2

    const/16 v5, 0x30

    aput-boolean v8, v7, v5

    goto :goto_2

    :cond_2
    const/16 v10, 0x31

    aput-boolean v8, v7, v10

    .line 230
    invoke-virtual {v5, v8}, Landroidx/recyclerview/widget/RecyclerView;->setHasFixedSize(Z)V

    const/16 v5, 0x32

    aput-boolean v8, v7, v5

    .line 231
    iget-object v5, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->yearSelector:Landroidx/recyclerview/widget/RecyclerView;

    new-instance v10, Landroidx/recyclerview/widget/GridLayoutManager;

    const/4 v11, 0x0

    invoke-direct {v10, v15, v4, v8, v11}, Landroidx/recyclerview/widget/GridLayoutManager;-><init>(Landroid/content/Context;IIZ)V

    invoke-virtual {v5, v10}, Landroidx/recyclerview/widget/RecyclerView;->setLayoutManager(Landroidx/recyclerview/widget/RecyclerView$LayoutManager;)V

    const/16 v5, 0x33

    aput-boolean v8, v7, v5

    .line 233
    iget-object v5, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->yearSelector:Landroidx/recyclerview/widget/RecyclerView;

    new-instance v10, Lcom/google/android/material/datepicker/YearGridAdapter;

    invoke-direct {v10, v6}, Lcom/google/android/material/datepicker/YearGridAdapter;-><init>(Lcom/google/android/material/datepicker/MaterialCalendar;)V

    invoke-virtual {v5, v10}, Landroidx/recyclerview/widget/RecyclerView;->setAdapter(Landroidx/recyclerview/widget/RecyclerView$Adapter;)V

    const/16 v5, 0x34

    aput-boolean v8, v7, v5

    .line 234
    iget-object v5, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->yearSelector:Landroidx/recyclerview/widget/RecyclerView;

    invoke-direct/range {p0 .. p0}, Lcom/google/android/material/datepicker/MaterialCalendar;->createItemDecoration()Landroidx/recyclerview/widget/RecyclerView$ItemDecoration;

    move-result-object v10

    invoke-virtual {v5, v10}, Landroidx/recyclerview/widget/RecyclerView;->addItemDecoration(Landroidx/recyclerview/widget/RecyclerView$ItemDecoration;)V

    const/16 v5, 0x35

    aput-boolean v8, v7, v5

    .line 237
    :goto_2
    sget v5, Lcom/google/android/material/R$id;->month_navigation_fragment_toggle:I

    invoke-virtual {v9, v5}, Landroid/view/View;->findViewById(I)Landroid/view/View;

    move-result-object v5

    if-nez v5, :cond_3

    const/16 v5, 0x36

    aput-boolean v8, v7, v5

    goto :goto_3

    :cond_3
    const/16 v5, 0x37

    aput-boolean v8, v7, v5

    .line 238
    invoke-direct {v6, v9, v1}, Lcom/google/android/material/datepicker/MaterialCalendar;->addActionsToMonthNavigation(Landroid/view/View;Lcom/google/android/material/datepicker/MonthsPagerAdapter;)V

    const/16 v5, 0x38

    aput-boolean v8, v7, v5

    .line 241
    :goto_3
    invoke-static {v15}, Lcom/google/android/material/datepicker/MaterialDatePicker;->isFullscreen(Landroid/content/Context;)Z

    move-result v5

    if-eqz v5, :cond_4

    const/16 v5, 0x39

    aput-boolean v8, v7, v5

    goto :goto_4

    :cond_4
    const/16 v5, 0x3a

    aput-boolean v8, v7, v5

    .line 242
    new-instance v5, Landroidx/recyclerview/widget/PagerSnapHelper;

    invoke-direct {v5}, Landroidx/recyclerview/widget/PagerSnapHelper;-><init>()V

    iget-object v10, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    invoke-virtual {v5, v10}, Landroidx/recyclerview/widget/PagerSnapHelper;->attachToRecyclerView(Landroidx/recyclerview/widget/RecyclerView;)V

    const/16 v5, 0x3b

    aput-boolean v8, v7, v5

    .line 244
    :goto_4
    iget-object v5, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->recyclerView:Landroidx/recyclerview/widget/RecyclerView;

    iget-object v10, v6, Lcom/google/android/material/datepicker/MaterialCalendar;->current:Lcom/google/android/material/datepicker/Month;

    invoke-virtual {v1, v10}, Lcom/google/android/material/datepicker/MonthsPagerAdapter;->getPosition(Lcom/google/android/material/datepicker/Month;)I

    move-result v10

    invoke-virtual {v5, v10}, Landroidx/recyclerview/widget/RecyclerView;->scrollToPosition(I)V

    const/16 v5, 0x3c

    aput-boolean v8, v7, v5

    .line 245
    invoke-direct/range {p0 .. p0}, Lcom/google/android/material/datepicker/MaterialCalendar;->setUpForAccessibility()V

    .line 246
    const/16 v5, 0x3d

    aput-boolean v8, v7, v5

    return-object v9
.end method

Jadx version

1.5.0

@pubiqq pubiqq added bug Core Issues in jadx-core module labels Aug 1, 2024
@skylot
Copy link
Owner

skylot commented Aug 2, 2024

@pubiqq thanks for notice!
So we can't rerun SSA transform after any insns inline, because it messes registers usage.
As I see such rerun used only in one place, so I will try to adjust vars manually without reset.

By the way, can you share a smali code for that method? It will really simplify writing a test case for this issue.

@skylot skylot self-assigned this Aug 2, 2024
@skylot skylot added this to the TBD milestone Aug 2, 2024
@pubiqq
Copy link
Contributor Author

pubiqq commented Aug 2, 2024

I've added a code to the description.

@skylot
Copy link
Owner

skylot commented Aug 2, 2024

Fixed 🙂

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Core Issues in jadx-core module regression
Projects
None yet
Development

No branches or pull requests

2 participants