fix: app crashes on YT Music v5.49.54+

This commit is contained in:
inotia00
2023-03-22 11:46:02 +09:00
parent d971a26cfa
commit 8250e9e3cb
3 changed files with 134 additions and 97 deletions

View File

@ -1,20 +1,78 @@
package app.revanced.patches.music.misc.litho.patch package app.revanced.patches.music.misc.litho.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility
import app.revanced.patches.shared.patch.litho.AbstractLithoFilterPatch import app.revanced.patches.shared.fingerprints.LithoFingerprint
import app.revanced.util.integrations.Constants.ADS_PATH import app.revanced.util.integrations.Constants.ADS_PATH
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
@YouTubeMusicCompatibility @YouTubeMusicCompatibility
@Version("0.0.1") @Version("0.0.1")
class MusicLithoFilterPatch : AbstractLithoFilterPatch( class MusicLithoFilterPatch : BytecodePatch(
"$ADS_PATH/MusicLithoFilterPatch;" listOf(
LithoFingerprint
)
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
super.execute(context) LithoFingerprint.result?.let { result ->
val endIndex = result.scanResult.patternScanResult!!.endIndex
val method = result.mutableMethod
with (method.implementation!!.instructions) {
val bufferIndex = indexOfFirst {
it.opcode == Opcode.CONST &&
(it as Instruction31i).narrowLiteral == 168777401
}
val bufferRegister = (method.instruction(bufferIndex) as Instruction31i).registerA
val targetIndex = indexOfFirst {
it.opcode == Opcode.CONST_STRING &&
(it as BuilderInstruction21c).reference.toString() == "Element missing type extension"
} + 2
val builderMethodDescriptor = (elementAt(targetIndex) as ReferenceInstruction).reference as MethodReference
val emptyComponentFieldDescriptor = (elementAt(targetIndex + 2) as ReferenceInstruction).reference as FieldReference
val identifierRegister = (method.instruction(endIndex) as OneRegisterInstruction).registerA
filter { instruction ->
val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference
fieldReference?.let { it.type == "Ljava/lang/StringBuilder;" } == true
}.forEach { instruction ->
val insertIndex = indexOf(instruction)
val stringBuilderRegister = (method.instruction(insertIndex) as TwoRegisterInstruction).registerA
method.addInstructions(
insertIndex, // right after setting the component.pathBuilder field,
"""
invoke-static {v$stringBuilderRegister, v$identifierRegister}, $ADS_PATH/MusicLithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z
move-result v$bufferRegister
if-eqz v$bufferRegister, :not_an_ad
move-object/from16 v$identifierRegister, p1
invoke-static {v$identifierRegister}, $builderMethodDescriptor
move-result-object v0
iget-object v0, v0, $emptyComponentFieldDescriptor
return-object v0
""", listOf(ExternalLabel("not_an_ad", method.instruction(insertIndex)))
)
}
}
} ?: return LithoFingerprint.toErrorResult()
return PatchResultSuccess() return PatchResultSuccess()
} }

View File

@ -1,89 +0,0 @@
package app.revanced.patches.shared.patch.litho
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.fingerprints.LithoFingerprint
import app.revanced.patches.shared.fingerprints.LithoObjectFingerprint
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
@Version("0.0.1")
abstract class AbstractLithoFilterPatch(
private val descriptor: String
) : BytecodePatch(
listOf(
LithoFingerprint,
LithoObjectFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
LithoObjectFingerprint.result?.let {
val endIndex = it.scanResult.patternScanResult!!.endIndex
objectRegister = (it.mutableMethod.instruction(endIndex) as BuilderInstruction35c).registerC
} ?: return LithoObjectFingerprint.toErrorResult()
LithoFingerprint.result?.let { result ->
val endIndex = result.scanResult.patternScanResult!!.endIndex
val method = result.mutableMethod
with (method.implementation!!.instructions) {
val targetIndex = indexOfFirst {
it.opcode == Opcode.CONST_STRING &&
(it as BuilderInstruction21c).reference.toString() == "Element missing type extension"
} + 2
val builderMethodDescriptor = (elementAt(targetIndex) as ReferenceInstruction).reference as MethodReference
val emptyComponentFieldDescriptor = (elementAt(targetIndex + 2) as ReferenceInstruction).reference as FieldReference
val identifierRegister = (method.instruction(endIndex) as OneRegisterInstruction).registerA
val bytebufferRegister = method.implementation!!.registerCount - method.parameters.size + 2
val secondParameter = method.parameters[2]
filter { instruction ->
val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference
fieldReference?.let { it.type == "Ljava/lang/StringBuilder;" } == true
}.forEach { instruction ->
val insertIndex = indexOf(instruction) + 1
val stringBuilderRegister = (method.instruction(insertIndex) as OneRegisterInstruction).registerA
val clobberedRegister = (method.instruction(insertIndex + 1) as TwoRegisterInstruction).registerA
method.addInstructions(
insertIndex, // right after setting the component.pathBuilder field,
"""
move-object/from16 v$clobberedRegister, v$bytebufferRegister
iget-object v$clobberedRegister, v$clobberedRegister, $secondParameter->b:Ljava/nio/ByteBuffer;
invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister, v$clobberedRegister}, $descriptor->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;Ljava/nio/ByteBuffer;)Z
move-result v$clobberedRegister
if-eqz v$clobberedRegister, :not_an_ad
move-object/from16 v$identifierRegister, p1
invoke-static {v$identifierRegister}, $builderMethodDescriptor
move-result-object v0
iget-object v0, v0, $emptyComponentFieldDescriptor
return-object v0
""",listOf(ExternalLabel("not_an_ad", method.instruction(insertIndex)))
)
}
}
} ?: return LithoFingerprint.toErrorResult()
return PatchResultSuccess()
}
private companion object {
private var objectRegister: Int = 3
}
}

View File

@ -1,16 +1,30 @@
package app.revanced.patches.youtube.misc.litho.patch package app.revanced.patches.youtube.misc.litho.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.litho.AbstractLithoFilterPatch import app.revanced.patches.shared.fingerprints.LithoFingerprint
import app.revanced.patches.shared.fingerprints.LithoObjectFingerprint
import app.revanced.patches.youtube.ads.doublebacktoclose.patch.DoubleBackToClosePatch import app.revanced.patches.youtube.ads.doublebacktoclose.patch.DoubleBackToClosePatch
import app.revanced.patches.youtube.ads.swiperefresh.patch.SwipeRefreshPatch import app.revanced.patches.youtube.ads.swiperefresh.patch.SwipeRefreshPatch
import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus
import app.revanced.util.integrations.Constants.ADS_PATH import app.revanced.util.integrations.Constants.ADS_PATH
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
@DependsOn( @DependsOn(
[ [
@ -20,14 +34,68 @@ import app.revanced.util.integrations.Constants.ADS_PATH
) )
@YouTubeCompatibility @YouTubeCompatibility
@Version("0.0.1") @Version("0.0.1")
class LithoFilterPatch : AbstractLithoFilterPatch( class LithoFilterPatch : BytecodePatch(
"$ADS_PATH/LithoFilterPatch;" listOf(
LithoFingerprint,
LithoObjectFingerprint
)
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
super.execute(context) LithoObjectFingerprint.result?.let {
val endIndex = it.scanResult.patternScanResult!!.endIndex
objectRegister = (it.mutableMethod.instruction(endIndex) as BuilderInstruction35c).registerC
} ?: return LithoObjectFingerprint.toErrorResult()
LithoFingerprint.result?.let { result ->
val endIndex = result.scanResult.patternScanResult!!.endIndex
val method = result.mutableMethod
with (method.implementation!!.instructions) {
val targetIndex = indexOfFirst {
it.opcode == Opcode.CONST_STRING &&
(it as BuilderInstruction21c).reference.toString() == "Element missing type extension"
} + 2
val builderMethodDescriptor = (elementAt(targetIndex) as ReferenceInstruction).reference as MethodReference
val emptyComponentFieldDescriptor = (elementAt(targetIndex + 2) as ReferenceInstruction).reference as FieldReference
val identifierRegister = (method.instruction(endIndex) as OneRegisterInstruction).registerA
val bytebufferRegister = method.implementation!!.registerCount - method.parameters.size + 2
val secondParameter = method.parameters[2]
filter { instruction ->
val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference
fieldReference?.let { it.type == "Ljava/lang/StringBuilder;" } == true
}.forEach { instruction ->
val insertIndex = indexOf(instruction) + 1
val stringBuilderRegister = (method.instruction(insertIndex) as OneRegisterInstruction).registerA
val clobberedRegister = (method.instruction(insertIndex + 1) as TwoRegisterInstruction).registerA
method.addInstructions(
insertIndex, // right after setting the component.pathBuilder field,
"""
move-object/from16 v$clobberedRegister, v$bytebufferRegister
iget-object v$clobberedRegister, v$clobberedRegister, $secondParameter->b:Ljava/nio/ByteBuffer;
invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister, v$clobberedRegister}, $ADS_PATH/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;Ljava/nio/ByteBuffer;)Z
move-result v$clobberedRegister
if-eqz v$clobberedRegister, :not_an_ad
move-object/from16 v$identifierRegister, p1
invoke-static {v$identifierRegister}, $builderMethodDescriptor
move-result-object v0
iget-object v0, v0, $emptyComponentFieldDescriptor
return-object v0
""",listOf(ExternalLabel("not_an_ad", method.instruction(insertIndex)))
)
}
}
} ?: return LithoFingerprint.toErrorResult()
context.updatePatchStatus("ByteBuffer") context.updatePatchStatus("ByteBuffer")
return PatchResultSuccess() return PatchResultSuccess()
} }
private companion object {
private var objectRegister: Int = 3
}
} }