Skip to content
New issue

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

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

Already on GitHub? Sign in 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 🙂

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

No branches or pull requests

2 participants