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

feat(OpeningHours): Add Fix crash patch #2697

Merged
merged 6 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,12 @@ public final class app/revanced/patches/nyx/misc/pro/UnlockProPatch : app/revanc
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package app.revanced.patches.openinghours.misc.fix.crash

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.newLabel
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.openinghours.misc.fix.crash.fingerprints.SetPlaceFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

@Patch(
name = "Fix crash",
compatiblePackages = [CompatiblePackage("de.simon.openinghours", ["1.0"])],
)
@Suppress("unused")
object FixCrashPatch : BytecodePatch(
setOf(SetPlaceFingerprint),
) {

override fun execute(context: BytecodeContext) {
SetPlaceFingerprint.result?.let {
val indexedInstructions = it.mutableMethod.getInstructions().withIndex().toList()

/**
* This function replaces all `checkNotNull` instructions in the integer interval
* from [startIndex] to [endIndex], both inclusive. In place of the `checkNotNull`
* instruction an if-null check is inserted. If the if-null check yields that
* the value is indeed null, we jump to a newly created label at `endIndex + 1`.
*/
fun avoidNullPointerException(startIndex: Int, endIndex: Int) {
val continueLabel = it.mutableMethod.newLabel(endIndex + 1)

for (index in startIndex..endIndex) {
val instruction = indexedInstructions[index].value

if (!instruction.isCheckNotNullInstruction) {
continue
}

val checkNotNullInstruction = instruction as FiveRegisterInstruction
val originalRegister = checkNotNullInstruction.registerC

it.mutableMethod.replaceInstruction(
index,
BuilderInstruction21t(
Opcode.IF_EQZ,
originalRegister,
continueLabel,
),
)
}
}

val getOpeningHoursIndex = getIndicesOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/models/Place;",
"getOpeningHours",
)

val setWeekDayTextIndex = getIndexOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/views/custom/PlaceCard;",
"setWeekDayText",
)

val startCalculateStatusIndex = getIndexOfInvoke(
indexedInstructions,
"Lde/simon/openinghours/views/custom/PlaceCard;",
"startCalculateStatus",
)

// Replace the Intrinsics;->checkNotNull instructions with a null check
// and jump to our newly created label if it returns true.
// This avoids the NullPointerExceptions.
avoidNullPointerException(getOpeningHoursIndex[1], startCalculateStatusIndex)
avoidNullPointerException(getOpeningHoursIndex[0], setWeekDayTextIndex)
} ?: throw SetPlaceFingerprint.exception
}

private fun isInvokeInstruction(instruction: Instruction, className: String, methodName: String): Boolean {
val methodRef = instruction.getReference<MethodReference>() ?: return false
return methodRef.definingClass == className && methodRef.name == methodName
}

private fun getIndicesOfInvoke(
instructions: List<IndexedValue<Instruction>>,
className: String,
methodName: String,
): List<Int> = instructions.mapNotNull { (index, instruction) ->
if (isInvokeInstruction(instruction, className, methodName)) {
index
} else {
null
}
}

private fun getIndexOfInvoke(
instructions: List<IndexedValue<Instruction>>,
className: String,
methodName: String,
): Int = instructions.first { (_, instruction) ->
isInvokeInstruction(instruction, className, methodName)
}.index

private val Instruction.isCheckNotNullInstruction
get() = isInvokeInstruction(this, "Lkotlin/jvm/internal/Intrinsics;", "checkNotNull")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.revanced.patches.openinghours.misc.fix.crash.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object SetPlaceFingerprint : MethodFingerprint(
"V",
parameters = listOf("Lde/simon/openinghours/models/Place;"),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lde/simon/openinghours/views/custom/PlaceCard;" &&
methodDef.name == "setPlace"
},
)
Loading