From adf772b5aed2271084dc36025e105821d4d8508d Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Sun, 12 Apr 2026 22:31:27 +0200 Subject: [PATCH] Correctly handle null thisObject in VectorChain for static methods The previous implementation used a dummy `Any()` instance as a fallback when `thisObj` was null. This incorrectly bound an object instance to static method calls and prevented the terminal handler from receiving the required null pointer. We move core progression logic into a private `internalProceed` method that accepts a nullable `thisObject`. Moreover, we update libxposed submodule to include recent documentation changes (no API changes required). --- xposed/libxposed | 2 +- .../org/matrix/vector/impl/hooks/VectorChain.kt | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/xposed/libxposed b/xposed/libxposed index eb63ec2c4..edeb8379c 160000 --- a/xposed/libxposed +++ b/xposed/libxposed @@ -1 +1 @@ -Subproject commit eb63ec2c49a34a9c3cd08a7eee2b5cd8332f46d2 +Subproject commit edeb8379c067b16b91af3cb526f5f04db25c06b6 diff --git a/xposed/src/main/kotlin/org/matrix/vector/impl/hooks/VectorChain.kt b/xposed/src/main/kotlin/org/matrix/vector/impl/hooks/VectorChain.kt index cd8b75058..caa7f44f1 100644 --- a/xposed/src/main/kotlin/org/matrix/vector/impl/hooks/VectorChain.kt +++ b/xposed/src/main/kotlin/org/matrix/vector/impl/hooks/VectorChain.kt @@ -42,13 +42,15 @@ class VectorChain( override fun getArg(index: Int): Any? = args[index] - override fun proceed(): Any? = proceedWith(thisObj ?: Any(), args) + override fun proceed(): Any? = internalProceed(thisObj, args) - override fun proceed(args: Array): Any? = proceedWith(thisObj ?: Any(), args) + override fun proceed(args: Array): Any? = internalProceed(thisObj, args) - override fun proceedWith(thisObject: Any): Any? = proceedWith(thisObject, args) + override fun proceedWith(thisObject: Any): Any? = internalProceed(thisObject, args) - override fun proceedWith(thisObject: Any, args: Array): Any? { + override fun proceedWith(thisObject: Any, args: Array): Any? = internalProceed(thisObject, args) + + private fun internalProceed(thisObject: Any?, currentArgs: Array): Any? { proceedCalled = true // Reached the end of the modern hooks; trigger the original executable (and legacy hooks) @@ -86,7 +88,7 @@ class VectorChain( t: Throwable, record: VectorHookRecord, nextChain: VectorChain, - recoveryThis: Any, + recoveryThis: Any?, recoveryArgs: Array, ): Any? { // Check if the exception originated from downstream (lower hooks or original method) @@ -103,7 +105,7 @@ class VectorChain( if (!nextChain.proceedCalled) { // Crash occurred before calling proceed(); skip hooker and continue the chain Utils.logD("Hooker [$hookerName] crashed before proceed. Skipping.", t) - return nextChain.proceedWith(recoveryThis, recoveryArgs) + return nextChain.internalProceed(recoveryThis, recoveryArgs) } else { // Crash occurred after calling proceed(); suppress and restore downstream state Utils.logD("Hooker [$hookerName] crashed after proceed. Restoring state.", t)