From d524e4be3ea97a732a80bbe00daacecb8d7356c5 Mon Sep 17 00:00:00 2001 From: 1fexd Date: Fri, 4 Oct 2024 20:54:16 +0200 Subject: [PATCH 01/11] fix(sync): Fix Reddit video downloader parsing --- api/revanced-patches.api | 6 +++ .../fix/video/FixRedditVideoDownloadPatch.kt | 52 +++++++++++++++++++ .../RedditVideoRequestFingerprint.kt | 9 ++++ 3 files changed, 67 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index ad04ff075e..32db724760 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -840,6 +840,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/u public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch; + 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/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch { public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch; } diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt new file mode 100644 index 0000000000..49b417f428 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt @@ -0,0 +1,52 @@ +package app.revanced.patches.reddit.customclients.syncforreddit.fix.video + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.RedditVideoRequestFingerprint +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode + +@Patch( + name = "Fix Reddit video download", + description = "Fixes a bug in Sync's MPD parser resulting in only the audio-track being saved", + compatiblePackages = [ + CompatiblePackage("com.laurencedawson.reddit_sync"), + CompatiblePackage("com.laurencedawson.reddit_sync.pro"), + CompatiblePackage("com.laurencedawson.reddit_sync.dev"), + ], + requiresIntegrations = true, + use = false, +) +@Suppress("unused") +object FixRedditVideoDownloadPatch : BytecodePatch( + fingerprints = setOf(RedditVideoRequestFingerprint), +) { + private const val integrationsClassDescriptor = "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" + private const val getLinksMethod = "getLinks([B)[Ljava/lang/String;" + + override fun execute(context: BytecodeContext) { + val downloadMethod = RedditVideoRequestFingerprint.resultOrThrow().mutableMethod + val constIdx = downloadMethod.indexOfFirstInstruction { opcode == Opcode.CONST_WIDE_32 } - 2 + + downloadMethod.addInstructions(constIdx, """ + iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B + invoke-static { v2 }, $integrationsClassDescriptor->$getLinksMethod + move-result-object v2 + + # videoUrl at idx 0 + const/4 v5, 0x0 + aget-object v3, v2, v5 + + # audioUrl at idx 1 + const/4 v6, 0x1 + aget-object v4, v2, v6 + """.trimIndent()) + + downloadMethod.removeInstructions(0, constIdx) + } +} diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt new file mode 100644 index 0000000000..0c9115288f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object RedditVideoRequestFingerprint : MethodFingerprint( + customFingerprint = { methodDef, classDef -> + classDef.sourceFile == "RedditVideoRequest.java" && methodDef.name == "parseNetworkResponse" + } +) From a1681c9e1e6e8db4cd82434a00518c9a9285e3a0 Mon Sep 17 00:00:00 2001 From: 1fexd <58902674+1fexd@users.noreply.github.com> Date: Fri, 4 Oct 2024 19:45:24 +0000 Subject: [PATCH 02/11] Update src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt Co-authored-by: oSumAtrIX --- .../syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt index 49b417f428..0f34c765bd 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt @@ -12,7 +12,7 @@ import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @Patch( - name = "Fix Reddit video download", + name = "Fix video downloads", description = "Fixes a bug in Sync's MPD parser resulting in only the audio-track being saved", compatiblePackages = [ CompatiblePackage("com.laurencedawson.reddit_sync"), From 6bd2616310cb033874622be020f490a2024fa3f1 Mon Sep 17 00:00:00 2001 From: 1fexd <58902674+1fexd@users.noreply.github.com> Date: Fri, 4 Oct 2024 19:45:35 +0000 Subject: [PATCH 03/11] Update src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt Co-authored-by: oSumAtrIX --- .../syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt index 0f34c765bd..1716d27901 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt @@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.Opcode @Patch( name = "Fix video downloads", - description = "Fixes a bug in Sync's MPD parser resulting in only the audio-track being saved", + description = "Fixes a bug in Sync's MPD parser resulting in only the audio-track being saved.", compatiblePackages = [ CompatiblePackage("com.laurencedawson.reddit_sync"), CompatiblePackage("com.laurencedawson.reddit_sync.pro"), From d1d0e17a2a53cdd69fe70eab36309d5716a086b5 Mon Sep 17 00:00:00 2001 From: 1fexd Date: Fri, 4 Oct 2024 21:47:09 +0200 Subject: [PATCH 04/11] chore: Apply code review suggestions --- ...VideoDownloadPatch.kt => FixVideoDownloadsPatch.kt} | 10 +++++----- ...t => ParseRedditVideoNetworkResponseFingerprint.kt} | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/{FixRedditVideoDownloadPatch.kt => FixVideoDownloadsPatch.kt} (86%) rename src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/{RedditVideoRequestFingerprint.kt => ParseRedditVideoNetworkResponseFingerprint.kt} (79%) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt similarity index 86% rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 1716d27901..998efabc7d 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.RedditVideoRequestFingerprint +import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.ParseRedditVideoNetworkResponseFingerprint import app.revanced.util.indexOfFirstInstruction import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -20,17 +20,17 @@ import com.android.tools.smali.dexlib2.Opcode CompatiblePackage("com.laurencedawson.reddit_sync.dev"), ], requiresIntegrations = true, - use = false, + use = true, ) @Suppress("unused") -object FixRedditVideoDownloadPatch : BytecodePatch( - fingerprints = setOf(RedditVideoRequestFingerprint), +object FixVideoDownloadsPatch : BytecodePatch( + fingerprints = setOf(ParseRedditVideoNetworkResponseFingerprint), ) { private const val integrationsClassDescriptor = "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" private const val getLinksMethod = "getLinks([B)[Ljava/lang/String;" override fun execute(context: BytecodeContext) { - val downloadMethod = RedditVideoRequestFingerprint.resultOrThrow().mutableMethod + val downloadMethod = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod val constIdx = downloadMethod.indexOfFirstInstruction { opcode == Opcode.CONST_WIDE_32 } - 2 downloadMethod.addInstructions(constIdx, """ diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt similarity index 79% rename from src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt rename to src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt index 0c9115288f..02b7acb26b 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/RedditVideoRequestFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.reddit.customclients.syncforreddit.fix.video.finger import app.revanced.patcher.fingerprint.MethodFingerprint -internal object RedditVideoRequestFingerprint : MethodFingerprint( +internal object ParseRedditVideoNetworkResponseFingerprint : MethodFingerprint( customFingerprint = { methodDef, classDef -> classDef.sourceFile == "RedditVideoRequest.java" && methodDef.name == "parseNetworkResponse" } From 43f37c9c4b09f5eada1487c71fe05bce257beae4 Mon Sep 17 00:00:00 2001 From: 1fexd Date: Fri, 4 Oct 2024 21:47:22 +0200 Subject: [PATCH 05/11] fix: Crash due to missing instruction --- .../syncforreddit/fix/video/FixVideoDownloadsPatch.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 998efabc7d..4e9a1f53a4 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -34,6 +34,7 @@ object FixVideoDownloadsPatch : BytecodePatch( val constIdx = downloadMethod.indexOfFirstInstruction { opcode == Opcode.CONST_WIDE_32 } - 2 downloadMethod.addInstructions(constIdx, """ + new-instance v0, Lo8/h; iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B invoke-static { v2 }, $integrationsClassDescriptor->$getLinksMethod move-result-object v2 From ab71db08f5637b415290ee237bde8eff72ee9090 Mon Sep 17 00:00:00 2001 From: 1fexd Date: Fri, 4 Oct 2024 21:48:12 +0200 Subject: [PATCH 06/11] chore: Apply code review suggestions --- .../syncforreddit/fix/video/FixVideoDownloadsPatch.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 4e9a1f53a4..0ea5b9d993 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -26,8 +26,8 @@ import com.android.tools.smali.dexlib2.Opcode object FixVideoDownloadsPatch : BytecodePatch( fingerprints = setOf(ParseRedditVideoNetworkResponseFingerprint), ) { - private const val integrationsClassDescriptor = "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" - private const val getLinksMethod = "getLinks([B)[Ljava/lang/String;" + private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" + private const val GET_LINKS_METHOD = "getLinks([B)[Ljava/lang/String;" override fun execute(context: BytecodeContext) { val downloadMethod = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod @@ -36,7 +36,7 @@ object FixVideoDownloadsPatch : BytecodePatch( downloadMethod.addInstructions(constIdx, """ new-instance v0, Lo8/h; iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B - invoke-static { v2 }, $integrationsClassDescriptor->$getLinksMethod + invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD move-result-object v2 # videoUrl at idx 0 From 8ae5d3ae39e3a7f0677c922f0fde188131c6f97a Mon Sep 17 00:00:00 2001 From: 1fexd Date: Fri, 4 Oct 2024 22:13:57 +0200 Subject: [PATCH 07/11] feat: Add comments, rework patch --- api/revanced-patches.api | 4 +-- .../fix/video/FixVideoDownloadsPatch.kt | 26 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 32db724760..56febe2d2f 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -840,8 +840,8 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/u public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } -public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch : app/revanced/patcher/patch/BytecodePatch { - public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixRedditVideoDownloadPatch; +public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 0ea5b9d993..9e605f9716 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -7,9 +7,10 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.ParseRedditVideoNetworkResponseFingerprint -import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @Patch( name = "Fix video downloads", @@ -31,23 +32,32 @@ object FixVideoDownloadsPatch : BytecodePatch( override fun execute(context: BytecodeContext) { val downloadMethod = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod - val constIdx = downloadMethod.indexOfFirstInstruction { opcode == Opcode.CONST_WIDE_32 } - 2 - downloadMethod.addInstructions(constIdx, """ - new-instance v0, Lo8/h; + // Find the instruction which creates the result data class + val newInstanceIdx = downloadMethod.indexOfFirstInstructionOrThrow { + opcode == Opcode.NEW_INSTANCE && (this as ReferenceInstruction).reference.toString() == "Lo8/h;" + } + + // Remove all instructions up to that point, we don't need them + downloadMethod.removeInstructions(0, newInstanceIdx) + + // new-instance instruction from above is now at idx 0, add patch directly after it + downloadMethod.addInstructions(1, """ + # Get byte array from response iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B + # Call integration method, move result (which is a string array: [videoUrl?, audioUrl?]) to v2 invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD move-result-object v2 - # videoUrl at idx 0 + # Get videoUrl from idx 0 and move it into v3 const/4 v5, 0x0 aget-object v3, v2, v5 - # audioUrl at idx 1 + # Get audioUrl from idx 0 and move it into v4 const/4 v6, 0x1 aget-object v4, v2, v6 + + # We are done, the following method instructions use v3 and v4 to build the response """.trimIndent()) - - downloadMethod.removeInstructions(0, constIdx) } } From 29b76e2b89549ad2d69864f17b0832068265fa0e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 8 Oct 2024 00:31:08 +0200 Subject: [PATCH 08/11] refactor --- .../fix/video/FixVideoDownloadsPatch.kt | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 9e605f9716..e1f8a96b4f 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -7,10 +7,11 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.ParseRedditVideoNetworkResponseFingerprint +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.TypeReference @Patch( name = "Fix video downloads", @@ -27,37 +28,44 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction object FixVideoDownloadsPatch : BytecodePatch( fingerprints = setOf(ParseRedditVideoNetworkResponseFingerprint), ) { - private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" + private const val INTEGRATIONS_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;" private const val GET_LINKS_METHOD = "getLinks([B)[Ljava/lang/String;" override fun execute(context: BytecodeContext) { - val downloadMethod = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod + ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod.apply { - // Find the instruction which creates the result data class - val newInstanceIdx = downloadMethod.indexOfFirstInstructionOrThrow { - opcode == Opcode.NEW_INSTANCE && (this as ReferenceInstruction).reference.toString() == "Lo8/h;" - } + // Find the instruction which creates the result data class. + val newInstanceIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.NEW_INSTANCE && getReference().toString() == "Lo8/h;" + } - // Remove all instructions up to that point, we don't need them - downloadMethod.removeInstructions(0, newInstanceIdx) + // Remove all instructions up to that point, because they are not needed anymore. + removeInstructions(0, newInstanceIndex) - // new-instance instruction from above is now at idx 0, add patch directly after it - downloadMethod.addInstructions(1, """ - # Get byte array from response - iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B - # Call integration method, move result (which is a string array: [videoUrl?, audioUrl?]) to v2 - invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD - move-result-object v2 - - # Get videoUrl from idx 0 and move it into v3 - const/4 v5, 0x0 - aget-object v3, v2, v5 + // new-instance instruction from above is now at index 0, add the patch directly after it. + addInstructions( + 1, + """ + # Get byte array from response. + iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B + + # Parse the videoUrl and audioUrl from the byte array. + invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD + move-result-object v2 + + # Get videoUrl (Index 0) and move it into v3. + const/4 v5, 0x0 + aget-object v3, v2, v5 + + # Get audioUrl (Index 1) and move it into v4. + const/4 v6, 0x1 + aget-object v4, v2, v6 + + # v3 and v4 is used to build the response after this. + """ + ) + } - # Get audioUrl from idx 0 and move it into v4 - const/4 v6, 0x1 - aget-object v4, v2, v6 - - # We are done, the following method instructions use v3 and v4 to build the response - """.trimIndent()) } } From 84a3f4f8991433b8a0bcef3dbcca7921b244ed44 Mon Sep 17 00:00:00 2001 From: 1fexd Date: Tue, 8 Oct 2024 07:33:17 +0200 Subject: [PATCH 09/11] Dynamically get registers --- .../fix/video/FixVideoDownloadsPatch.kt | 56 ++++++++----------- ...seRedditVideoNetworkResponseFingerprint.kt | 7 +++ 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index e1f8a96b4f..c1d7f0975c 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -2,16 +2,13 @@ package app.revanced.patches.reddit.customclients.syncforreddit.fix.video import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.ParseRedditVideoNetworkResponseFingerprint -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.reference.TypeReference +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c @Patch( name = "Fix video downloads", @@ -33,39 +30,32 @@ object FixVideoDownloadsPatch : BytecodePatch( private const val GET_LINKS_METHOD = "getLinks([B)[Ljava/lang/String;" override fun execute(context: BytecodeContext) { - ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().mutableMethod.apply { + val fingerprint = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow() + val scanResult = fingerprint.scanResult.patternScanResult!! + val newInstanceIndex = scanResult.startIndex + val invokeDirectIndex = scanResult.endIndex - 1 - // Find the instruction which creates the result data class. - val newInstanceIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.NEW_INSTANCE && getReference().toString() == "Lo8/h;" - } + fingerprint.mutableMethod.apply { + val responseBuilderInstruction = getInstruction(invokeDirectIndex) - // Remove all instructions up to that point, because they are not needed anymore. - removeInstructions(0, newInstanceIndex) - - // new-instance instruction from above is now at index 0, add the patch directly after it. - addInstructions( - 1, - """ - # Get byte array from response. - iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B + addInstructions(newInstanceIndex + 1, """ + # Get byte array from response. + iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B - # Parse the videoUrl and audioUrl from the byte array. - invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD - move-result-object v2 + # Parse the videoUrl and audioUrl from the byte array. + invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD + move-result-object v2 - # Get videoUrl (Index 0) and move it into v3. - const/4 v5, 0x0 - aget-object v3, v2, v5 + # Get videoUrl (Index 0) and move it into register (v3). + const/4 v5, 0x0 + aget-object v${responseBuilderInstruction.registerE}, v2, v5 - # Get audioUrl (Index 1) and move it into v4. - const/4 v6, 0x1 - aget-object v4, v2, v6 - - # v3 and v4 is used to build the response after this. - """ - ) - } + # Get audioUrl (Index 1) and move it into register (v4). + const/4 v6, 0x1 + aget-object v${responseBuilderInstruction.registerF}, v2, v6 + # v3 and v4 are used to build the response after this. + """) + } } } diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt index 02b7acb26b..1a06cd54d6 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/fingerprints/ParseRedditVideoNetworkResponseFingerprint.kt @@ -1,8 +1,15 @@ package app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode internal object ParseRedditVideoNetworkResponseFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.NEW_INSTANCE, + Opcode.IGET_OBJECT, + Opcode.INVOKE_DIRECT, + Opcode.CONST_WIDE_32 + ), customFingerprint = { methodDef, classDef -> classDef.sourceFile == "RedditVideoRequest.java" && methodDef.name == "parseNetworkResponse" } From 753d3a57535b9a39e18e6fac93eb9470344504d6 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 14 Oct 2024 14:11:42 +0200 Subject: [PATCH 10/11] Apply suggestions from code review --- .../syncforreddit/fix/video/FixVideoDownloadsPatch.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index c1d7f0975c..7c11009639 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -18,8 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c CompatiblePackage("com.laurencedawson.reddit_sync.pro"), CompatiblePackage("com.laurencedawson.reddit_sync.dev"), ], - requiresIntegrations = true, - use = true, + requiresIntegrations = true ) @Suppress("unused") object FixVideoDownloadsPatch : BytecodePatch( From 15a338ba5ec34dc486d924130bba3c3324683d3d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 17 Oct 2024 17:27:53 +0200 Subject: [PATCH 11/11] slight refactor --- .../fix/video/FixVideoDownloadsPatch.kt | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index 7c11009639..b228025c89 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -18,7 +18,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c CompatiblePackage("com.laurencedawson.reddit_sync.pro"), CompatiblePackage("com.laurencedawson.reddit_sync.dev"), ], - requiresIntegrations = true + requiresIntegrations = true, ) @Suppress("unused") object FixVideoDownloadsPatch : BytecodePatch( @@ -29,32 +29,34 @@ object FixVideoDownloadsPatch : BytecodePatch( private const val GET_LINKS_METHOD = "getLinks([B)[Ljava/lang/String;" override fun execute(context: BytecodeContext) { - val fingerprint = ParseRedditVideoNetworkResponseFingerprint.resultOrThrow() - val scanResult = fingerprint.scanResult.patternScanResult!! - val newInstanceIndex = scanResult.startIndex - val invokeDirectIndex = scanResult.endIndex - 1 + ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().let { + val scanResult = it.scanResult.patternScanResult!! + val newInstanceIndex = scanResult.startIndex + val invokeDirectIndex = scanResult.endIndex - 1 - fingerprint.mutableMethod.apply { - val responseBuilderInstruction = getInstruction(invokeDirectIndex) + val buildResponseInstruction = it.mutableMethod.getInstruction(invokeDirectIndex) - addInstructions(newInstanceIndex + 1, """ - # Get byte array from response. - iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B - - # Parse the videoUrl and audioUrl from the byte array. - invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD - move-result-object v2 - - # Get videoUrl (Index 0) and move it into register (v3). - const/4 v5, 0x0 - aget-object v${responseBuilderInstruction.registerE}, v2, v5 - - # Get audioUrl (Index 1) and move it into register (v4). - const/4 v6, 0x1 - aget-object v${responseBuilderInstruction.registerF}, v2, v6 - - # v3 and v4 are used to build the response after this. - """) + it.mutableMethod.addInstructions( + newInstanceIndex + 1, + """ + # Get byte array from response. + iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B + + # Parse the videoUrl and audioUrl from the byte array. + invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD + move-result-object v2 + + # Get videoUrl (Index 0). + const/4 v5, 0x0 + aget-object v${buildResponseInstruction.registerE}, v2, v5 + + # Get audioUrl (Index 1). + const/4 v6, 0x1 + aget-object v${buildResponseInstruction.registerF}, v2, v6 + + # Register E and F are used to build the response. + """, + ) } } }