From 1901e965e8341801a60805ab7a2a938e691da641 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:50:32 +0400 Subject: [PATCH] unofficial 20.41.33 --- .../ReturnYouTubeDislikePatch.kt | 28 +++++++++++++------ .../youtube/misc/litho/filter/Fingerprints.kt | 6 ---- .../misc/litho/filter/LithoFilterPatch.kt | 25 ++++++----------- .../patches/youtube/shared/Fingerprints.kt | 2 +- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index 4a13646999..2ff5851bb6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -124,12 +124,14 @@ val returnYouTubeDislikePatch = bytecodePatch( // This hook handles all situations, as it's where the created Spans are stored and later reused. // Find the field name of the conversion context. - val conversionContextField = textComponentConstructorFingerprint.originalClassDef.fields.find { - it.type == conversionContextFingerprintToString.originalClassDef.type + val conversionContextClass = conversionContextFingerprintToString.originalClassDef + val textComponentConversionContextField = textComponentConstructorFingerprint.originalClassDef.fields.find { + it.type == conversionContextClass.type + // 20.41+ uses superclass field type. + || it.type == conversionContextClass.superclass } ?: throw PatchException("Could not find conversion context field") - textComponentLookupFingerprint.match(textComponentConstructorFingerprint.originalClassDef) - .method.apply { + textComponentLookupFingerprint.match(textComponentConstructorFingerprint.originalClassDef).method.apply { // Find the instruction for creating the text data object. val textDataClassType = textComponentDataFingerprint.originalClassDef.type @@ -161,16 +163,26 @@ val returnYouTubeDislikePatch = bytecodePatch( charSequenceRegister = getInstruction(charSequenceIndex).registerA } - val tempRegister = findFreeRegister(insertIndex, charSequenceRegister) + val free1 = findFreeRegister(insertIndex, charSequenceRegister) + val free2 = findFreeRegister(insertIndex, charSequenceRegister, free1) addInstructionsAtControlFlowLabel( insertIndex, """ # Copy conversion context - move-object/from16 v$tempRegister, p0 - iget-object v$tempRegister, v$tempRegister, $conversionContextField - invoke-static { v$tempRegister, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + move-object/from16 v$free1, p0 + + # 20.41 field is the abstract superclass. + # Verify it's the expected subclass just in case. + instance-of v$free2, v$free1, ${textComponentConversionContextField.type} + if-eqz v$free2, :ignore + + check-cast v$free1, $conversionContextClass + invoke-static { v$free1, v$charSequenceRegister }, $EXTENSION_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; move-result-object v$charSequenceRegister + + :ignore + nop """ ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt index 0740c3b694..3faa497407 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt @@ -9,12 +9,6 @@ import app.revanced.patcher.string import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val componentContextParserFingerprint by fingerprint { - instructions( - string("Number of bits must be positive") - ) -} - internal val componentCreateFingerprint by fingerprint { instructions( string("Element missing correct type extension"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index b03d8147d6..d161a2c480 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -4,7 +4,6 @@ package app.revanced.patches.youtube.misc.litho.filter import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch @@ -16,16 +15,13 @@ import app.revanced.patches.youtube.misc.playservice.is_20_22_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.shared.conversionContextFingerprintToString import app.revanced.util.addInstructionsAtControlFlowLabel +import app.revanced.util.findFieldFromToString import app.revanced.util.findFreeRegister -import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.insertLiteralOverride import app.revanced.util.returnLate import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference import java.util.logging.Logger lateinit var addLithoFilter: (String) -> Unit @@ -125,18 +121,9 @@ val lithoFilterPatch = bytecodePatch( // if the component is filtered then return an empty component. // Find the identifier/path fields of the conversion context. - val conversionContextIdentifierField = componentContextParserFingerprint.match().let { - // Identifier field is loaded just before the string declaration. - val index = it.method.indexOfFirstInstructionReversedOrThrow( - it.instructionMatches.first().index - ) { - val reference = getReference() - reference?.definingClass == conversionContextFingerprintToString.originalClassDef.type - && reference.type == "Ljava/lang/String;" - } - it.method.getInstruction(index).getReference()!! - } + val conversionContextIdentifierField = conversionContextFingerprintToString.method + .findFieldFromToString("identifierProperty=") val conversionContextPathBuilderField = conversionContextFingerprintToString.originalClassDef .fields.single { field -> field.type == "Ljava/lang/StringBuilder;" } @@ -167,6 +154,12 @@ val lithoFilterPatch = bytecodePatch( insertIndex, """ move-object/from16 v$freeRegister, p2 + + # 20.41 field is the abstract superclass. + # Verify it's the expected subclass just in case. + instance-of v$identifierRegister, v$freeRegister, ${conversionContextFingerprintToString.classDef.type} + if-eqz v$identifierRegister, :unfiltered + iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField iget-object v$pathRegister, v$freeRegister, $conversionContextPathBuilderField invoke-static { v$identifierRegister, v$pathRegister }, $EXTENSION_CLASS_DESCRIPTOR->isFiltered(Ljava/lang/String;Ljava/lang/StringBuilder;)Z diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index fbfb0e8d75..d782462d44 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -17,7 +17,7 @@ internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/ internal val conversionContextFingerprintToString by fingerprint { parameters() strings( - "ConversionContext{containerInternal=", + "ConversionContext{", // Partial string match. ", widthConstraint=", ", heightConstraint=", ", templateLoggerFactory=",