ReVanced / revanced-patcher

💉 ReVanced Patcher used to patch Android applications
https://revanced.app
GNU General Public License v3.0
2.51k stars 208 forks source link

bug: `BytecodeContext#findClass(String)` Can find the wrong class #309

Open LisoUseInAIKyrios opened 1 week ago

LisoUseInAIKyrios commented 1 week ago

Bug description

Currently findClass works by only checking for contains:

    /**
     * Find a class by a given class name.
     *
     * @param className The name of the class.
     * @return A proxy for the first class that matches the class name.
     */
    fun findClass(className: String) = findClass { it.type.contains(className) }

But this can cause issues where the class desired is a substring of another class:

Labc; Labcdefg;

Calling context.findClass("abc") could return either abc or abcdefg

Error logs

No response

Solution

Check for exact class name using == (and not contains): fun findClass(className: String) = findClass { it.type == className }

Or if it's desirable to allow specifying class name only and not package, then maybe check with something like:

// Untested code, theoretical fix:
fun findClass(className: String) {
        if (className.startsWith('/')) {
            return it.type == "L$className;"
        }

        return it.type.endsWith("/$className;")
    }

Additional context

No response

Acknowledgements

oSumAtrIX commented 1 week ago

Looks like it could cause breaking changes in case someone already relies on this behavior. I think the API isn't that necessary since you have access to the class list and therefore can already find a class using any predicate you want. Therefore I'll consider deprecating the API

LisoUseInAIKyrios commented 6 days ago

The more immediate fix needed is MethodWalker, where it uses findClass() and can start walking from the wrong class:

https://github.com/ReVanced/revanced-patcher/blob/ceb6fd51c186f014303ead87ba592e0151e70891/src/main/kotlin/app/revanced/patcher/util/method/MethodWalker.kt#L39-L57

oSumAtrIX commented 6 days ago

you can use context.classes.find { it.type == className }

LisoUseInAIKyrios commented 6 days ago

Right, but method walker needs that change since it's in patcher and not patches repo.