Skip to content

Commit 1983e00

Browse files
committed
Correctly handle null thisObject in VectorChain for static methods (#658)
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).
1 parent ddcfa3d commit 1983e00

2 files changed

Lines changed: 13 additions & 10 deletions

File tree

xposed/src/main/kotlin/org/matrix/vector/impl/hooks/VectorChain.kt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,30 @@ class VectorChain(
4242

4343
override fun getArg(index: Int): Any? = args[index]
4444

45-
override fun proceed(): Any? = proceedWith(thisObj ?: Any(), args)
45+
override fun proceed(): Any? = internalProceed(thisObj, args)
4646

47-
override fun proceed(args: Array<Any?>): Any? = proceedWith(thisObj ?: Any(), args)
47+
override fun proceed(currentArgs: Array<Any?>): Any? = internalProceed(thisObj, currentArgs)
4848

49-
override fun proceedWith(thisObject: Any): Any? = proceedWith(thisObject, args)
49+
override fun proceedWith(thisObject: Any): Any? = internalProceed(thisObject, args)
5050

51-
override fun proceedWith(thisObject: Any, args: Array<Any?>): Any? {
51+
override fun proceedWith(thisObject: Any, currentArgs: Array<Any?>): Any? =
52+
internalProceed(thisObject, currentArgs)
53+
54+
private fun internalProceed(thisObject: Any?, currentArgs: Array<Any?>): Any? {
5255
proceedCalled = true
5356

5457
// Reached the end of the modern hooks; trigger the original executable (and legacy hooks)
5558
if (index >= hooks.size) {
56-
return executeDownstream { terminal(thisObject, args) }
59+
return executeDownstream { terminal(thisObject, currentArgs) }
5760
}
5861

5962
val record = hooks[index]
60-
val nextChain = VectorChain(executable, thisObject, args, hooks, index + 1, terminal)
63+
val nextChain = VectorChain(executable, thisObject, currentArgs, hooks, index + 1, terminal)
6164

6265
return try {
6366
executeDownstream { record.hooker.intercept(nextChain) }
6467
} catch (t: Throwable) {
65-
handleInterceptorException(t, record, nextChain, thisObject, args)
68+
handleInterceptorException(t, record, nextChain, thisObject, currentArgs)
6669
}
6770
}
6871

@@ -86,7 +89,7 @@ class VectorChain(
8689
t: Throwable,
8790
record: VectorHookRecord,
8891
nextChain: VectorChain,
89-
recoveryThis: Any,
92+
recoveryThis: Any?,
9093
recoveryArgs: Array<Any?>,
9194
): Any? {
9295
// Check if the exception originated from downstream (lower hooks or original method)
@@ -103,7 +106,7 @@ class VectorChain(
103106
if (!nextChain.proceedCalled) {
104107
// Crash occurred before calling proceed(); skip hooker and continue the chain
105108
Utils.logD("Hooker [$hookerName] crashed before proceed. Skipping.", t)
106-
return nextChain.proceedWith(recoveryThis, recoveryArgs)
109+
return nextChain.internalProceed(recoveryThis, recoveryArgs)
107110
} else {
108111
// Crash occurred after calling proceed(); suppress and restore downstream state
109112
Utils.logD("Hooker [$hookerName] crashed after proceed. Restoring state.", t)

0 commit comments

Comments
 (0)