Skip to content

Commit 6742cd9

Browse files
Linus789oSumAtrIX
andauthored
feat(OpeningHours): Add Fix crash patch (#2697)
Co-authored-by: oSumAtrIX <[email protected]>
1 parent 5b2cc10 commit 6742cd9

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

api/revanced-patches.api

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,12 @@ public final class app/revanced/patches/nyx/misc/pro/UnlockProPatch : app/revanc
410410
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
411411
}
412412

413+
public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch : app/revanced/patcher/patch/BytecodePatch {
414+
public static final field INSTANCE Lapp/revanced/patches/openinghours/misc/fix/crash/FixCrashPatch;
415+
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
416+
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
417+
}
418+
413419
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch : app/revanced/patcher/patch/BytecodePatch {
414420
public static final field INSTANCE Lapp/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatch;
415421
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package app.revanced.patches.openinghours.misc.fix.crash
2+
3+
import app.revanced.patcher.data.BytecodeContext
4+
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
5+
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
6+
import app.revanced.patcher.extensions.newLabel
7+
import app.revanced.patcher.patch.BytecodePatch
8+
import app.revanced.patcher.patch.annotation.CompatiblePackage
9+
import app.revanced.patcher.patch.annotation.Patch
10+
import app.revanced.patches.openinghours.misc.fix.crash.fingerprints.SetPlaceFingerprint
11+
import app.revanced.util.exception
12+
import app.revanced.util.getReference
13+
import com.android.tools.smali.dexlib2.Opcode
14+
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21t
15+
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
16+
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
17+
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
18+
19+
@Patch(
20+
name = "Fix crash",
21+
compatiblePackages = [CompatiblePackage("de.simon.openinghours", ["1.0"])],
22+
)
23+
@Suppress("unused")
24+
object FixCrashPatch : BytecodePatch(
25+
setOf(SetPlaceFingerprint),
26+
) {
27+
28+
override fun execute(context: BytecodeContext) {
29+
SetPlaceFingerprint.result?.let {
30+
val indexedInstructions = it.mutableMethod.getInstructions().withIndex().toList()
31+
32+
/**
33+
* This function replaces all `checkNotNull` instructions in the integer interval
34+
* from [startIndex] to [endIndex], both inclusive. In place of the `checkNotNull`
35+
* instruction an if-null check is inserted. If the if-null check yields that
36+
* the value is indeed null, we jump to a newly created label at `endIndex + 1`.
37+
*/
38+
fun avoidNullPointerException(startIndex: Int, endIndex: Int) {
39+
val continueLabel = it.mutableMethod.newLabel(endIndex + 1)
40+
41+
for (index in startIndex..endIndex) {
42+
val instruction = indexedInstructions[index].value
43+
44+
if (!instruction.isCheckNotNullInstruction) {
45+
continue
46+
}
47+
48+
val checkNotNullInstruction = instruction as FiveRegisterInstruction
49+
val originalRegister = checkNotNullInstruction.registerC
50+
51+
it.mutableMethod.replaceInstruction(
52+
index,
53+
BuilderInstruction21t(
54+
Opcode.IF_EQZ,
55+
originalRegister,
56+
continueLabel,
57+
),
58+
)
59+
}
60+
}
61+
62+
val getOpeningHoursIndex = getIndicesOfInvoke(
63+
indexedInstructions,
64+
"Lde/simon/openinghours/models/Place;",
65+
"getOpeningHours",
66+
)
67+
68+
val setWeekDayTextIndex = getIndexOfInvoke(
69+
indexedInstructions,
70+
"Lde/simon/openinghours/views/custom/PlaceCard;",
71+
"setWeekDayText",
72+
)
73+
74+
val startCalculateStatusIndex = getIndexOfInvoke(
75+
indexedInstructions,
76+
"Lde/simon/openinghours/views/custom/PlaceCard;",
77+
"startCalculateStatus",
78+
)
79+
80+
// Replace the Intrinsics;->checkNotNull instructions with a null check
81+
// and jump to our newly created label if it returns true.
82+
// This avoids the NullPointerExceptions.
83+
avoidNullPointerException(getOpeningHoursIndex[1], startCalculateStatusIndex)
84+
avoidNullPointerException(getOpeningHoursIndex[0], setWeekDayTextIndex)
85+
} ?: throw SetPlaceFingerprint.exception
86+
}
87+
88+
private fun isInvokeInstruction(instruction: Instruction, className: String, methodName: String): Boolean {
89+
val methodRef = instruction.getReference<MethodReference>() ?: return false
90+
return methodRef.definingClass == className && methodRef.name == methodName
91+
}
92+
93+
private fun getIndicesOfInvoke(
94+
instructions: List<IndexedValue<Instruction>>,
95+
className: String,
96+
methodName: String,
97+
): List<Int> = instructions.mapNotNull { (index, instruction) ->
98+
if (isInvokeInstruction(instruction, className, methodName)) {
99+
index
100+
} else {
101+
null
102+
}
103+
}
104+
105+
private fun getIndexOfInvoke(
106+
instructions: List<IndexedValue<Instruction>>,
107+
className: String,
108+
methodName: String,
109+
): Int = instructions.first { (_, instruction) ->
110+
isInvokeInstruction(instruction, className, methodName)
111+
}.index
112+
113+
private val Instruction.isCheckNotNullInstruction
114+
get() = isInvokeInstruction(this, "Lkotlin/jvm/internal/Intrinsics;", "checkNotNull")
115+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package app.revanced.patches.openinghours.misc.fix.crash.fingerprints
2+
3+
import app.revanced.patcher.fingerprint.MethodFingerprint
4+
5+
internal object SetPlaceFingerprint : MethodFingerprint(
6+
"V",
7+
parameters = listOf("Lde/simon/openinghours/models/Place;"),
8+
customFingerprint = { methodDef, _ ->
9+
methodDef.definingClass == "Lde/simon/openinghours/views/custom/PlaceCard;" &&
10+
methodDef.name == "setPlace"
11+
},
12+
)

0 commit comments

Comments
 (0)