1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-10 05:30:49 +02:00

Compare commits

..

13 Commits

Author SHA1 Message Date
semantic-release-bot
fa0412985c chore(release): 1.0.0-dev.8 [skip ci]
# [1.0.0-dev.8](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2022-03-24)

### Performance Improvements

* check type instead of class ([47eb493](47eb493f54))
2022-03-24 22:38:45 +00:00
Lucaskyy
0048788dd0 Merge remote-tracking branch 'origin/dev' into dev 2022-03-24 23:37:34 +01:00
Lucaskyy
47eb493f54 perf: check type instead of class
this is way better, thank you oSumAtrIX!
2022-03-24 23:37:28 +01:00
semantic-release-bot
6b1337e4fc chore(release): 1.0.0-dev.7 [skip ci]
# [1.0.0-dev.7](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2022-03-24)

### Bug Fixes

* **MethodResolver:** fix cd57a8c9a0 ([1af31b2](1af31b2aa3))
2022-03-24 22:31:58 +00:00
Lucaskyy
f4589db3a9 test: fix assert message 2022-03-24 23:31:01 +01:00
Lucaskyy
1af31b2aa3 fix(MethodResolver): fix cd57a8c9a0 2022-03-24 23:29:32 +01:00
semantic-release-bot
14f7667156 chore(release): 1.0.0-dev.6 [skip ci]
# [1.0.0-dev.6](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2022-03-24)

### Bug Fixes

* **MethodResolver:** strip labels nodes so opcode patterns match ([cd57a8c](cd57a8c9a0))
2022-03-24 21:49:47 +00:00
Lucaskyy
cd57a8c9a0 fix(MethodResolver): strip labels nodes so opcode patterns match
this commit is also a fix for 8d1bb5f3d9 because it corrupted the stack by completely removing the nodes
2022-03-24 22:48:34 +01:00
Lucaskyy
0d3beb353d Merge remote-tracking branch 'origin/dev' into dev 2022-03-24 21:38:22 +01:00
Lucaskyy
ddef338631 refactor: log as trace instead of debug
so there's less spam in console
2022-03-24 21:38:13 +01:00
semantic-release-bot
fc4b673087 chore(release): 1.0.0-dev.5 [skip ci]
# [1.0.0-dev.5](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2022-03-24)

### Bug Fixes

* **MethodResolver:** strip labels and line numbers so opcode patterns match ([8d1bb5f](8d1bb5f3d9))
2022-03-24 20:30:54 +00:00
Lucaskyy
8d1bb5f3d9 fix(MethodResolver): strip labels and line numbers so opcode patterns match 2022-03-24 21:27:44 +01:00
Lucaskyy
c8a017a4c0 refactor: only compute maxs and use existing stack frames 2022-03-24 19:45:13 +01:00
6 changed files with 69 additions and 30 deletions

View File

@@ -1,3 +1,31 @@
# [1.0.0-dev.8](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2022-03-24)
### Performance Improvements
* check type instead of class ([47eb493](https://github.com/ReVancedTeam/revanced-patcher/commit/47eb493f5425dc27a4d6e79e6b02a36ef760e8da))
# [1.0.0-dev.7](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2022-03-24)
### Bug Fixes
* **MethodResolver:** fix cd57a8c9a0db7e3ae5ad0bca202e5955930319ab ([1af31b2](https://github.com/ReVancedTeam/revanced-patcher/commit/1af31b2aa3772a7473c04d27bf835c8eae13438d))
# [1.0.0-dev.6](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2022-03-24)
### Bug Fixes
* **MethodResolver:** strip labels nodes so opcode patterns match ([cd57a8c](https://github.com/ReVancedTeam/revanced-patcher/commit/cd57a8c9a0db7e3ae5ad0bca202e5955930319ab))
# [1.0.0-dev.5](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2022-03-24)
### Bug Fixes
* **MethodResolver:** strip labels and line numbers so opcode patterns match ([8d1bb5f](https://github.com/ReVancedTeam/revanced-patcher/commit/8d1bb5f3d9da544cf6e3e3848bfcc56327cde810))
# [1.0.0-dev.4](https://github.com/ReVancedTeam/revanced-patcher/compare/v1.0.0-dev.3...v1.0.0-dev.4) (2022-03-23)

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official
version = 1.0.0-dev.4
version = 1.0.0-dev.8

View File

@@ -1,15 +1,13 @@
package app.revanced.patcher.resolver
import mu.KotlinLogging
import app.revanced.patcher.cache.MethodMap
import app.revanced.patcher.cache.PatchData
import app.revanced.patcher.cache.PatternScanData
import app.revanced.patcher.signature.Signature
import app.revanced.patcher.util.ExtraTypes
import mu.KotlinLogging
import org.objectweb.asm.Type
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.InsnList
import org.objectweb.asm.tree.MethodNode
import org.objectweb.asm.tree.*
private val logger = KotlinLogging.logger("MethodResolver")
@@ -21,16 +19,16 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
for (method in methods) {
for (signature in signatures) {
if (methodMap.containsKey(signature.name)) { // method already found for this sig
logger.debug { "Sig ${signature.name} already found, skipping." }
logger.trace { "Sig ${signature.name} already found, skipping." }
continue
}
logger.debug { "Resolving sig ${signature.name}: ${classNode.name} / ${method.name}" }
logger.trace { "Resolving sig ${signature.name}: ${classNode.name} / ${method.name}" }
val (r, sr) = cmp(method, signature)
if (!r || sr == null) {
logger.debug { "Compare result for sig ${signature.name} has failed!" }
logger.trace { "Compare result for sig ${signature.name} has failed!" }
continue
}
logger.debug { "Method for sig ${signature.name} found!" }
logger.trace { "Method for sig ${signature.name} found!" }
methodMap[signature.name] = PatchData(
classNode,
method,
@@ -71,7 +69,7 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
signature.returns?.let { _ ->
val methodReturns = Type.getReturnType(method.desc).convertObject()
if (signature.returns != methodReturns) {
logger.debug {
logger.trace {
"""
Comparing sig ${signature.name}: invalid return type:
expected ${signature.returns},
@@ -84,7 +82,7 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
signature.accessors?.let { _ ->
if (signature.accessors != method.access) {
logger.debug {
logger.trace {
"""
Comparing sig ${signature.name}: invalid accessors:
expected ${signature.accessors},
@@ -98,7 +96,7 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
signature.parameters?.let { _ ->
val parameters = Type.getArgumentTypes(method.desc).convertObjects()
if (!signature.parameters.contentEquals(parameters)) {
logger.debug {
logger.trace {
"""
Comparing sig ${signature.name}: invalid parameter types:
expected ${signature.parameters.joinToString()}},
@@ -112,7 +110,7 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
signature.opcodes?.let { _ ->
val result = method.instructions.scanFor(signature.opcodes)
if (!result.found) {
logger.debug { "Comparing sig ${signature.name}: invalid opcode pattern" }
logger.trace { "Comparing sig ${signature.name}: invalid opcode pattern" }
return@cmp false to null
}
return@cmp true to result
@@ -123,19 +121,15 @@ internal class MethodResolver(private val classList: List<ClassNode>, private va
}
}
private operator fun ClassNode.component1(): ClassNode {
return this
}
private operator fun ClassNode.component2(): List<MethodNode> {
return this.methods
}
private operator fun ClassNode.component1() = this
private operator fun ClassNode.component2() = this.methods
private fun InsnList.scanFor(pattern: IntArray): ScanResult {
for (i in 0 until this.size()) {
var occurrence = 0
while (i + occurrence < this.size()) {
if (this[i + occurrence].opcode != pattern[occurrence]) break
val n = this[i + occurrence]
if (!n.shouldSkip() && n.opcode != pattern[occurrence]) break
if (++occurrence >= pattern.size) {
val current = i + occurrence
return ScanResult(true, current - pattern.size, current)
@@ -157,3 +151,6 @@ private fun Type.convertObject(): Type {
private fun Array<Type>.convertObjects(): Array<Type> {
return this.map { it.convertObject() }.toTypedArray()
}
private fun AbstractInsnNode.shouldSkip() =
type == AbstractInsnNode.LABEL || type == AbstractInsnNode.LINE

View File

@@ -79,10 +79,7 @@ internal class Io(
jos.putNextEntry(JarEntry(name))
// parse the patched class to a byte array and write it to the output stream
val cw = ClassWriter(
classReaders[name]!!,
ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS
)
val cw = ClassWriter(classReaders[name]!!, ClassWriter.COMPUTE_MAXS)
patchedClass.accept(cw)
jos.write(cw.toByteArray())

View File

@@ -39,8 +39,10 @@ internal class PatcherTest {
ACC_PUBLIC or ACC_STATIC,
arrayOf(ExtraTypes.ArrayAny),
intArrayOf(
GETSTATIC,
LDC,
INVOKEVIRTUAL
INVOKEVIRTUAL,
RETURN
)
)
)
@@ -66,7 +68,19 @@ internal class PatcherTest {
// Get the start index of our opcode pattern.
// This will be the index of the LDC instruction.
val startIndex = mainMethod.scanData.startIndex
TestUtil.assertNodeEqual(LdcInsnNode("Hello, world!"), instructions[startIndex]!!)
// Ignore this, just testing if the method resolver works :)
TestUtil.assertNodeEqual(
FieldInsnNode(
GETSTATIC,
Type.getInternalName(System::class.java),
"out",
// for whatever reason, it adds an "L" and ";" to the node string
"L${Type.getInternalName(PrintStream::class.java)};"
),
instructions[startIndex]!!
)
// Create a new LDC node and replace the LDC instruction.
val stringNode = LdcInsnNode("Hello, ReVanced! Editing bytecode.")
instructions.setAt(startIndex, stringNode)
@@ -82,7 +96,7 @@ internal class PatcherTest {
GETSTATIC,
Type.getInternalName(System::class.java), // "java/lang/System"
"out",
"L" + Type.getInternalName(PrintStream::class.java) // "Ljava/io/PrintStream"
Type.getInternalName(PrintStream::class.java) // "java/io/PrintStream"
),
LdcInsnNode("Hello, ReVanced! Adding bytecode."),
MethodInsnNode(
@@ -143,7 +157,9 @@ internal class PatcherTest {
fun `should not raise an exception if any signature member except the name is missing`() {
val sigName = "testMethod"
assertDoesNotThrow("Should raise an exception because opcodes is empty") {
assertDoesNotThrow(
"Should not raise an exception if any signature member except the name is missing"
) {
Patcher(
PatcherTest::class.java.getResourceAsStream("/test1.jar")!!,
ByteArrayOutputStream(),

View File

@@ -38,7 +38,8 @@ private class NodeStringBuilder {
}
override fun toString(): String {
if (sb.isEmpty()) return ""
val s = sb.toString()
return s.substring(0 until s.length - 2) // remove the last ", "
return s.substring(0 .. (s.length - 2).coerceAtLeast(0)) // remove the last ", "
}
}