feat(YouTube): Support versions 19.25 and 19.34 (#3629)

Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
Zain 2024-10-19 19:26:39 +07:00 committed by GitHub
parent c9c7f01a2f
commit 049e7f0813
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
141 changed files with 2284 additions and 2261 deletions

View file

@ -3,6 +3,9 @@ package app.revanced.util
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
@ -15,7 +18,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.util.MethodUtil
import org.stringtemplate.v4.compiler.Bytecode.instructions
fun MethodFingerprint.resultOrThrow() = result ?: throw exception
@ -66,6 +68,37 @@ fun MutableMethod.injectHideViewCall(
"invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V",
)
/**
* Inserts instructions at a given index, using the existing control flow label at that index.
* Inserted instructions can have it's own control flow labels as well.
*
* Effectively this changes the code from:
* :label
* (original code)
*
* Into:
* :label
* (patch code)
* (original code)
*/
internal fun MutableMethod.addInstructionsAtControlFlowLabel(
insertIndex: Int,
instructions: String,
) {
// Duplicate original instruction and add to +1 index.
addInstruction(insertIndex + 1, getInstruction(insertIndex))
// Add patch code at same index as duplicated instruction,
// so it uses the original instruction control flow label.
addInstructionsWithLabels(insertIndex + 1, instructions)
// Remove original non duplicated instruction.
removeInstruction(insertIndex)
// Original instruction is now after the inserted patch instructions,
// and the original control flow label is on the first instruction of the patch code.
}
/**
* Get the index of the first instruction with the id of the given resource name.
*
@ -98,6 +131,9 @@ fun Method.indexOfIdResourceOrThrow(resourceName: String): Int {
return index
}
// TODO Rename these from 'FirstWideLiteralInstruction' to 'FirstLiteralInstruction',
// since NarrowLiteralInstruction is a subclass of WideLiteralInstruction.
/**
* Find the index of the first wide literal instruction with the given value.
*
@ -189,6 +225,23 @@ inline fun <reified T : Reference> Instruction.getReference() = (this as? Refere
// @Deprecated("Use the overloaded method with an optional start index.", ReplaceWith("indexOfFirstInstruction(predicate)"))
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = indexOfFirstInstruction(0, predicate)
/**
* @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow
*/
fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int =
indexOfFirstInstruction(0, targetOpcode)
/**
* @param startIndex Optional starting index to start searching from.
* @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow
*/
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int =
indexOfFirstInstruction(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
*
@ -197,7 +250,11 @@ fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = index
* @see indexOfFirstInstructionOrThrow
*/
fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.() -> Boolean): Int {
val index = this.implementation!!.instructions.drop(startIndex).indexOfFirst(predicate)
var instructions = this.implementation!!.instructions
if (startIndex != 0) {
instructions = instructions.drop(startIndex)
}
val index = instructions.indexOfFirst(predicate)
return if (index >= 0) {
startIndex + index
@ -206,6 +263,24 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.(
}
}
/**
* @return The index of the first opcode specified
* @throws PatchException
* @see indexOfFirstInstruction
*/
fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int =
indexOfFirstInstructionOrThrow(0, targetOpcode)
/**
* @return The index of the first opcode specified, starting from the index specified.
* @throws PatchException
* @see indexOfFirstInstruction
*/
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int =
indexOfFirstInstructionOrThrow(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
*
@ -218,6 +293,68 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, predicate: Instru
if (index < 0) {
throw PatchException("Could not find instruction index")
}
return index
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversedOrThrow
*/
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int =
indexOfFirstInstructionReversed(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversedOrThrow
*/
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, predicate: Instruction.() -> Boolean): Int {
var instructions = this.implementation!!.instructions
if (startIndex != null) {
instructions = instructions.take(startIndex + 1)
}
return instructions.indexOfLast(predicate)
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversed
*/
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int =
indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversed
*/
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, predicate: Instruction.() -> Boolean): Int {
val index = indexOfFirstInstructionReversed(startIndex, predicate)
if (index < 0) {
throw PatchException("Could not find instruction index")
}
return index
}
@ -242,6 +379,26 @@ fun Method.findOpcodeIndicesReversed(filter: Instruction.() -> Boolean): List<In
return indexes
}
/**
* Called for _all_ instructions with the given literal value.
*/
fun BytecodeContext.forEachLiteralValueInstruction(
literal: Long,
block: MutableMethod.(literalInstructionIndex: Int) -> Unit,
) {
classes.forEach { classDef ->
classDef.methods.forEach { method ->
method.implementation?.instructions?.forEachIndexed { index, instruction ->
if (instruction.opcode == Opcode.CONST &&
(instruction as WideLiteralInstruction).wideLiteral == literal
) {
val mutableMethod = proxy(classDef).mutableClass.findMutableMethodOf(method)
block.invoke(mutableMethod, index)
}
}
}
}
}
/**
* Return the resolved method early.