From e5361e90fe052c92dfcb47cc362fcf84bec3540b Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:12:29 +0900 Subject: [PATCH] feat(Utils): Use more Contexts for activities/services to avoid NullPointerException in Context.getResources() --- .../extension/shared/utils/Utils.java | 12 ++++- .../utils/extension/SharedExtensionPatch.kt | 10 +++- .../hooks/MainActivityBaseContextHook.kt | 32 +++++++++++++ .../hooks/CronetEngineContextHook.kt | 48 +++++++++++++++++++ .../hooks/FirebaseInitProviderContextHook.kt | 37 ++++++++++++++ .../utils/extension/SharedExtensionPatch.kt | 6 +++ .../hooks/UrlActivityBaseContextHook.kt | 32 +++++++++++++ 7 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 patches/src/main/kotlin/app/revanced/patches/music/utils/extension/hooks/MainActivityBaseContextHook.kt create mode 100644 patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/CronetEngineContextHook.kt create mode 100644 patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/FirebaseInitProviderContextHook.kt create mode 100644 patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/UrlActivityBaseContextHook.kt diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java index ed3e96428..e1290d73f 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/utils/Utils.java @@ -359,7 +359,17 @@ public class Utils { // // Info level also helps debug if a patch hook is called before // the context is set since debug logging is off by default. - Logger.initializationInfo(Utils.class, "Set context: " + appContext); + StringBuilder sb = new StringBuilder(); + sb.append("Set context: "); + sb.append(appContext); + StackTraceElement[] stackTraceElement = Thread.currentThread().getStackTrace(); + if (stackTraceElement.length > 3) { + sb.append("\n"); + sb.append("Called from method: "); + sb.append(stackTraceElement[3]); + } + + Logger.initializationInfo(Utils.class, sb.toString()); } public static void setClipboard(@NonNull String text) { diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/SharedExtensionPatch.kt index 2151b9af5..dd6883783 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/SharedExtensionPatch.kt @@ -1,6 +1,14 @@ package app.revanced.patches.music.utils.extension import app.revanced.patches.music.utils.extension.hooks.applicationInitHook +import app.revanced.patches.music.utils.extension.hooks.mainActivityBaseContextHook +import app.revanced.patches.shared.extension.hooks.cronetEngineContextHook +import app.revanced.patches.shared.extension.hooks.firebaseInitProviderContextHook import app.revanced.patches.shared.extension.sharedExtensionPatch -val sharedExtensionPatch = sharedExtensionPatch(applicationInitHook) +val sharedExtensionPatch = sharedExtensionPatch( + applicationInitHook, + cronetEngineContextHook, + firebaseInitProviderContextHook, + mainActivityBaseContextHook, +) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/hooks/MainActivityBaseContextHook.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/hooks/MainActivityBaseContextHook.kt new file mode 100644 index 000000000..549eff2ba --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/extension/hooks/MainActivityBaseContextHook.kt @@ -0,0 +1,32 @@ +package app.revanced.patches.music.utils.extension.hooks + +import app.revanced.patches.shared.extension.extensionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private var attachBaseContextIndex = -1 + +internal val mainActivityBaseContextHook = extensionHook( + insertIndexResolver = { method -> + attachBaseContextIndex = method.indexOfFirstInstructionOrThrow { + getReference()?.name == "attachBaseContext" + } + + attachBaseContextIndex + 1 + }, + contextRegisterResolver = { method -> + val overrideInstruction = + method.implementation!!.instructions.elementAt(attachBaseContextIndex) + as FiveRegisterInstruction + "v${overrideInstruction.registerD}" + }, +) { + returns("V") + parameters("Landroid/content/Context;") + custom { method, classDef -> + classDef.type == "Lcom/google/android/apps/youtube/music/activities/MusicActivity;" && + method.name == "attachBaseContext" + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/CronetEngineContextHook.kt b/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/CronetEngineContextHook.kt new file mode 100644 index 000000000..e31cf801b --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/CronetEngineContextHook.kt @@ -0,0 +1,48 @@ +package app.revanced.patches.shared.extension.hooks + +import app.revanced.patches.shared.extension.extensionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private var initIndex = -1 +private var isRange = true + +internal val cronetEngineContextHook = extensionHook( + insertIndexResolver = { method -> + initIndex = method.indexOfFirstInstruction(Opcode.INVOKE_DIRECT_RANGE) + + if (initIndex < 0) { + initIndex = method.indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT) + isRange = false + } + + initIndex + }, + contextRegisterResolver = { method -> + val initInstruction = + method.implementation!!.instructions.elementAt(initIndex) + if (isRange) { + val overrideInstruction = initInstruction as Instruction3rc + "v${overrideInstruction.startRegister + 1}" + } else { + val overrideInstruction = initInstruction as FiveRegisterInstruction + "v${overrideInstruction.registerD}" + } + }, +) { + returns("Lorg/chromium/net/CronetEngine;") + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + strings("Could not create CronetEngine") + custom { method, classDef -> + method.indexOfFirstInstruction { + (opcode == Opcode.INVOKE_DIRECT || opcode == Opcode.INVOKE_DIRECT_RANGE) && + getReference()?.parameterTypes?.firstOrNull() == "Landroid/content/Context;" + } >= 0 + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/FirebaseInitProviderContextHook.kt b/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/FirebaseInitProviderContextHook.kt new file mode 100644 index 000000000..e52f23dfa --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/shared/extension/hooks/FirebaseInitProviderContextHook.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.shared.extension.hooks + +import app.revanced.patches.shared.extension.extensionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private var getResourcesIndex = -1 + +internal val firebaseInitProviderContextHook = extensionHook( + insertIndexResolver = { method -> + getResourcesIndex = indexOfGerResourcesInstruction(method) + + getResourcesIndex + 2 + }, + contextRegisterResolver = { method -> + val overrideInstruction = + method.implementation!!.instructions.elementAt(getResourcesIndex) + as FiveRegisterInstruction + + "v${overrideInstruction.registerC}" + }, +) { + strings("firebase_database_url") + custom { method, _ -> + indexOfGerResourcesInstruction(method) >= 0 + } +} + +private fun indexOfGerResourcesInstruction(method: Method) = + method.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.toString() =="Landroid/content/Context;->getResources()Landroid/content/res/Resources;" + } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt index 263d4fb8c..e2ba7dc77 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/SharedExtensionPatch.kt @@ -1,11 +1,17 @@ package app.revanced.patches.youtube.utils.extension +import app.revanced.patches.shared.extension.hooks.cronetEngineContextHook +import app.revanced.patches.shared.extension.hooks.firebaseInitProviderContextHook import app.revanced.patches.shared.extension.sharedExtensionPatch import app.revanced.patches.youtube.utils.extension.hooks.applicationInitHook import app.revanced.patches.youtube.utils.extension.hooks.mainActivityBaseContextHook +import app.revanced.patches.youtube.utils.extension.hooks.urlActivityBaseContextHook // TODO: Move this to a "Hook.kt" file. Same for other extension hook patches. val sharedExtensionPatch = sharedExtensionPatch( applicationInitHook, + cronetEngineContextHook, + firebaseInitProviderContextHook, mainActivityBaseContextHook, + urlActivityBaseContextHook, ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/UrlActivityBaseContextHook.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/UrlActivityBaseContextHook.kt new file mode 100644 index 000000000..b14d0b71e --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/extension/hooks/UrlActivityBaseContextHook.kt @@ -0,0 +1,32 @@ +package app.revanced.patches.youtube.utils.extension.hooks + +import app.revanced.patches.shared.extension.extensionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private var attachBaseContextIndex = -1 + +internal val urlActivityBaseContextHook = extensionHook( + insertIndexResolver = { method -> + attachBaseContextIndex = method.indexOfFirstInstructionOrThrow { + getReference()?.name == "attachBaseContext" + } + + attachBaseContextIndex + 1 + }, + contextRegisterResolver = { method -> + val overrideInstruction = + method.implementation!!.instructions.elementAt(attachBaseContextIndex) + as FiveRegisterInstruction + "v${overrideInstruction.registerD}" + }, +) { + returns("V") + parameters("Landroid/content/Context;") + custom { method, classDef -> + classDef.endsWith("/Shell_UrlActivity;") && + method.name == "attachBaseContext" + } +}