Closed PurpleTunic closed 1 year ago
Please attach a full stack trace.
My guess: infinite recursion happens in the class app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0
because this class does not start with Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch
. One way to fix this is to not use a lambda for the fallback, but to return a boolean whether the fallback should run. Not sure if there is a better way, but perhaps you have another idea @oSumAtrIX?
We need the full stack trace. In the class LithoBlockRegister
there is no reference which SpoofWifiPatch
could patch out
In the class LithoBlockRegister there is no reference which SpoofWifiPatch could patch out
It will patch out invoke-virtual { p0, p1 }, Landroid/net/ConnectivityManager;->registerDefaultNetworkCallback(Landroid/net/ConnectivityManager$NetworkCallback;)V
in that class. Smali disassembler shows it, but FernFlower does not.
The class LithoBlockRegister
should not reference ConnectivityManager
. My experience has been best with jadx, a Dex to Java decompiler.
Well, but it does reference it. And our integrations class calls this function in the LithoBlockRegister
which ultimately leads to infinite recursion. I’m using the Bytecode Viewer application.
Can you link the line of code which has said reference?
Here is the full smali disassembly of that class:
.class public final Lapp/revanced/integrations/patches/LithoBlockRegister$$ExternalSyntheticApiModelOutline0;
.super Ljava/lang/Object;
.method public static bridge m(Landroid/net/ConnectivityManager;Landroid/net/ConnectivityManager$NetworkCallback;)V
.registers 2
invoke-virtual { p0, p1 }, Landroid/net/ConnectivityManager;->registerDefaultNetworkCallback(Landroid/net/ConnectivityManager$NetworkCallback;)V
return-void
.end method
.method public static bridge m(Ljava/util/ArrayList;Ljava/util/function/Consumer;)V
.registers 2
invoke-virtual { p0, p1 }, Ljava/util/ArrayList;->forEach(Ljava/util/function/Consumer;)V
return-void
.end method
And in our integrations class:
import app.revanced.integrations.patches.LithoBlockRegister..ExternalSyntheticApiModelOutline0;
[...]
private static void lambda$registerDefaultNetworkCallback$1(ConnectivityManager var0, ConnectivityManager.NetworkCallback var1) {
ExternalSyntheticApiModelOutline0.m(var0, var1);
}
@Linus789 This is offtopic, but Bytecode Viewer uses Dex2Jar, which assembles back the Dalvik bytecode to Java, which is hacky. On the other hand, jadx integrates a native disassembler and many useful tools like renaming, finding references and more.
Interesting, thanks for the info.
@Linus789 Here is the full dissassembly of the compiled class LithoBlockRegister
from revanced-integrations
:
###### Class app.revanced.integrations.patches.LithoBlockRegister (app.revanced.integrations.patches.LithoBlockRegister)
.class final Lapp/revanced/integrations/patches/LithoBlockRegister;
.super Ljava/lang/Object;
.source "LithoFilterPatch.java"
# interfaces
.implements Ljava/lang/Iterable;
# annotations
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/lang/Object;",
"Ljava/lang/Iterable<",
"Lapp/revanced/integrations/patches/BlockRule;",
">;"
}
.end annotation
# instance fields
.field private final blocks:Ljava/util/ArrayList;
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/util/ArrayList<",
"Lapp/revanced/integrations/patches/BlockRule;",
">;"
}
.end annotation
.end field
# direct methods
.method constructor <init>()V
.registers 2
.line 80
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
.line 81
new-instance v0, Ljava/util/ArrayList;
invoke-direct {v0}, Ljava/util/ArrayList;-><init>()V
iput-object v0, p0, Lapp/revanced/integrations/patches/LithoBlockRegister;->blocks:Ljava/util/ArrayList;
return-void
.end method
# virtual methods
.method public contains(Ljava/lang/String;)Z
.registers 6
.param p1, "path" # Ljava/lang/String;
.line 107
invoke-virtual {p0}, Lapp/revanced/integrations/patches/LithoBlockRegister;->iterator()Ljava/util/Iterator;
move-result-object v0
:goto_4
invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z
move-result v1
if-eqz v1, :cond_24
invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;
move-result-object v1
check-cast v1, Lapp/revanced/integrations/patches/BlockRule;
.line 108
.local v1, "rule":Lapp/revanced/integrations/patches/BlockRule;
invoke-virtual {v1}, Lapp/revanced/integrations/patches/BlockRule;->isEnabled()Z
move-result v2
if-nez v2, :cond_17
goto :goto_4
.line 110
:cond_17
invoke-virtual {v1, p1}, Lapp/revanced/integrations/patches/BlockRule;->check(Ljava/lang/String;)Lapp/revanced/integrations/patches/BlockRule$BlockResult;
move-result-object v2
.line 111
.local v2, "result":Lapp/revanced/integrations/patches/BlockRule$BlockResult;
invoke-virtual {v2}, Lapp/revanced/integrations/patches/BlockRule$BlockResult;->isBlocked()Z
move-result v3
if-eqz v3, :cond_23
.line 112
const/4 v0, 0x1
return v0
.line 114
.end local v1 # "rule":Lapp/revanced/integrations/patches/BlockRule;
.end local v2 # "result":Lapp/revanced/integrations/patches/BlockRule$BlockResult;
:cond_23
goto :goto_4
.line 116
:cond_24
const/4 v0, 0x0
return v0
.end method
.method public forEach(Ljava/util/function/Consumer;)V
.registers 3
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Ljava/util/function/Consumer<",
"-",
"Lapp/revanced/integrations/patches/BlockRule;",
">;)V"
}
.end annotation
.line 96
.local p1, "action":Ljava/util/function/Consumer;, "Ljava/util/function/Consumer<-Lapp/revanced/integrations/patches/BlockRule;>;"
iget-object v0, p0, Lapp/revanced/integrations/patches/LithoBlockRegister;->blocks:Ljava/util/ArrayList;
invoke-virtual {v0, p1}, Ljava/util/ArrayList;->forEach(Ljava/util/function/Consumer;)V
.line 97
return-void
.end method
.method public iterator()Ljava/util/Iterator;
.registers 2
.annotation system Ldalvik/annotation/Signature;
value = {
"()",
"Ljava/util/Iterator<",
"Lapp/revanced/integrations/patches/BlockRule;",
">;"
}
.end annotation
.line 90
iget-object v0, p0, Lapp/revanced/integrations/patches/LithoBlockRegister;->blocks:Ljava/util/ArrayList;
invoke-virtual {v0}, Ljava/util/ArrayList;->iterator()Ljava/util/Iterator;
move-result-object v0
return-object v0
.end method
.method public varargs registerAll([Lapp/revanced/integrations/patches/BlockRule;)V
.registers 4
.param p1, "blocks" # [Lapp/revanced/integrations/patches/BlockRule;
.line 84
iget-object v0, p0, Lapp/revanced/integrations/patches/LithoBlockRegister;->blocks:Ljava/util/ArrayList;
invoke-static {p1}, Ljava/util/Arrays;->asList([Ljava/lang/Object;)Ljava/util/List;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->addAll(Ljava/util/Collection;)Z
.line 85
return-void
.end method
.method public spliterator()Ljava/util/Spliterator;
.registers 2
.annotation system Ldalvik/annotation/Signature;
value = {
"()",
"Ljava/util/Spliterator<",
"Lapp/revanced/integrations/patches/BlockRule;",
">;"
}
.end annotation
.line 103
iget-object v0, p0, Lapp/revanced/integrations/patches/LithoBlockRegister;->blocks:Ljava/util/ArrayList;
invoke-virtual {v0}, Ljava/util/ArrayList;->spliterator()Ljava/util/Spliterator;
move-result-object v0
return-object v0
.end method
No reference to ConnectivityManager
can be found. Maybe your disassembly is after patching and thus caused by the patch?
This is the smali I got from jadx:
###### Class app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0 (app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0)
.class public final synthetic Lapp/revanced/integrations/patches/LithoBlockRegister$$ExternalSyntheticApiModelOutline0;
.super Ljava/lang/Object;
.source "R8$$SyntheticClass"
# direct methods
.method public static bridge synthetic m(Landroid/net/ConnectivityManager;Landroid/net/ConnectivityManager$NetworkCallback;)V
.registers 2
invoke-virtual {p0, p1}, Landroid/net/ConnectivityManager;->registerDefaultNetworkCallback(Landroid/net/ConnectivityManager$NetworkCallback;)V
return-void
.end method
.method public static bridge synthetic m(Ljava/util/ArrayList;Ljava/util/function/Consumer;)V
.registers 2
invoke-virtual {p0, p1}, Ljava/util/ArrayList;->forEach(Ljava/util/function/Consumer;)V
return-void
.end method
And I’m using the .apk that has been created by integrations, so no patches have been applied.
The difference: I’m using LithoBlockRegister$$ExternalSyntheticApiModelOutline0
and you use LithoBlockRegister
.
That is odd. Said (compiler autogenerated) class does not exist in the dex file of revanced-integrations
:
I guess this issue come from R8. I added -printmapping
to proguard-rules.pro and get this mapping file.
mapping.txt
As you can see in line 710, method app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$$InternalSyntheticApiModelOutline$1$d379d1458b2457da6ca3cd27e0b559adbdecd343e6583d8baad3bf6e1f08ee86$0.m was moved to LithoBlockRegister$$ExternalSyntheticApiModelOutline0.m
I guess change this https://github.com/revanced/revanced-integrations/blob/d16153408c70e0dd100487426878cc2fd33b9a1b/app/build.gradle.kts#L24 to false should solve the issue. But I am not sure disable it is a good idea.
Oh, that makes sense. Thanks for the info @d4rkk3y.
@d4rkk3y That woild explain it. Though instead of didabling minification alltogether, does an annotation for classes exist from ProGuard to prevent any change to them?
But it didn't work with lambda.
The compiler generates this class in the same package this excludes. The debug
build of revanced-integration
does not contain the class LithoBlockRegister$$ExternalSyntheticApiModelOutline0
.
The class in release
build reveals compiled from R8$$SyntheticClass
. The question is, why does R8 move the code to this class?
The class in
release
build revealscompiled from R8$$SyntheticClass
. The question is, why does R8 move the code to this class?
I guess that happened as a type of optimization. But I don't know what happened exactly. I guess skimming R8 source code is a final option which is hard for me.
An alternative solution is for the patch to ignore the integrations completely.
This seems to help:
-keepclassmembernames class ** {
synthetic *** *(...);
}
Perhaps it is possible to only exclude revanced lambdas?
Seems like -keepclassmembernames
requires the class specification, which does not have any specification for lambdas
In that case how about adding the snippet to the proguard config as is?
Because it's a workaround and not a fix, adding it causes the unintended side effect of disabling this setting for synthetic methods just for the sake of a patch. Imo the patch should involve a fix for the integrations and not the other way round.
What are the disadvantages of disabling this setting for synthetic methods?
Depends on what ProGuard does to them.
Well, the alternative to ignore the integrations completely is also just a workaround, since the spoof wifi patch will then ignore other patches, which it shouldn’t.
The fix would be to ignore applying the ProGuard settings to the patch class. That way, only for spoof-wifi
this option to disable the ProGuard setting is applied. Alternatively, your patch can dynamically analyse its class methods and build a list of methods it should whitelist from patching.
The fix would be to ignore applying the ProGuard settings to the patch class. That way, only for
spoof-wifi
this option to disable the ProGuard setting is applied.
I don’t know ProGuard that well. Could you help with that?
Alternatively, your patch can dynamically analyse its class methods and build a list of methods it should whitelist from patching.
I don’t think that’s a good and reliable solution.
I believe you can set the name in the class specification:
-keepclassmembernames class SpoofWifiPatch {
synthetic *** *(...);
}
I believe you can set the name in the class specification:
-keepclassmembernames class SpoofWifiPatch { synthetic *** *(...); }
Doesn’t seem to work for me.
One way to fix this is to not use a lambda for the fallback, but to return a boolean whether the fallback should run.
Another workaround that doesn’t solve the root problem would be my first suggestion. What do you think of that?
I believe you can set the name in the class specification:
-keepclassmembernames class SpoofWifiPatch { synthetic *** *(...); }
Doesn’t seem to work for me.
Did you use the correct name? Are those methods synthetic?
Did you use the correct name? Are those methods synthetic?
I just copied your snippet. I don’t know why it doesn’t work. Does the snippet work for you?
No, I gave it a suggestion, you have to put in the correct class name as well other matching attributes like the method modifier if you want to exclude methods with specific modifiers.
Neither
-keepclassmembernames class **SpoofWifiPatch** {
synthetic *** *(...);
}
nor
-keepclassmembernames class ** {
synthetic *** *SpoofWifiPatch*(...);
}
work. Therefore, I suggest to remove the lambas in the patch like I stated in my first proposal. Are you okay with that?
The motivation to remove the lambda should not be driven by the fact that ProGuard messes with it. It is required to fix this issue on ProGuard's side and not work around ProGuard on the side of the integrations.
Maybe the class LithoBlockRegister
has to be specified with -keepclassmembernames
?
The motivation to remove the lambda should not be driven by the fact that ProGuard messes with it. It is required to fix this issue on ProGuard's side and not work around ProGuard on the side of the integrations.
Sure, I can agree with that. But changing the ProGuard rules for every patch that doesn’t want to modify their integrations lambdas seems like a workaround as well. Using
-keepclassmembernames class ** {
synthetic *** *(...);
}
would work, but we might lose some ProGuard optimizations (though I’m not too sure, if losing these optimizations would impact the application at all).
Maybe the class
LithoBlockRegister
has to be specified with-keepclassmembernames
?
I’m not too sure if that is a reliable way. Can we be sure the name LithoBlockRegister
will never change in the future?
I was only able to keep class member names with
-keepclassmembernames class ** {
*;
}
I was not able to specify the class name like you. Further research on ProGuard has to be done to find out why in order to only specify the class in question.
I have tried specifying LithoBlockRegister
but unfortunately that also didn't work. A solution off the top of my head would be to annoate the class and then specify the annotation in the class spec in the ProGuard configuration file.
I was not able to specify the class name like you.
I haven’t been able to specify a class name either.
Further research on ProGuard has to be done to find out why in order to only specify the class in question.
Yes, but there is no guarantee that we will have a better solution afterwards. I don’t want to invest too much time into this issue.
A solution off the top of my head would be to annoate the class and then specify the annotation in the class spec in the ProGuard configuration file.
If it works, I’m not opposed to it. I’m not too sure that it will work, since specifying SpoofWifiPatch
as class name didn’t work either. Did you already try that solution?
Not sure if this is related but when installing with nonroot I only see the Vanced logo with a black background. ADB Logcat shows the following stack trace which just keeps repeating:
E YouTube : Background Thread Uncaught Exception, log serverside
E YouTube : java.lang.StackOverflowError: stack size 1039KB
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.activeWifiNetwork(SpoofWifiPatch.java:1)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.networkCallback(SpoofWifiPatch.java:3)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.-$$Nest$smnetworkCallback(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.registerDefaultNetworkCallback(SpoofWifiPatch.java:5)
E YouTube : at app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0.m(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.lambda$registerDefaultNetworkCallback$1(SpoofWifiPatch.java:1)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.$r8$lambda$YPpdCidDTKU3al2lYw5d3YS74ac(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$$ExternalSyntheticLambda9.run(Unknown Source:14)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.networkCallback(SpoofWifiPatch.java:11)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.-$$Nest$smnetworkCallback(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.registerDefaultNetworkCallback(SpoofWifiPatch.java:5)
E YouTube : at app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0.m(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.lambda$registerDefaultNetworkCallback$1(SpoofWifiPatch.java:1)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.$r8$lambda$YPpdCidDTKU3al2lYw5d3YS74ac(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$$ExternalSyntheticLambda9.run(Unknown Source:14)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.networkCallback(SpoofWifiPatch.java:11)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.-$$Nest$smnetworkCallback(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.registerDefaultNetworkCallback(SpoofWifiPatch.java:5)
E YouTube : at app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0.m(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.lambda$registerDefaultNetworkCallback$1(SpoofWifiPatch.java:1)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.$r8$lambda$YPpdCidDTKU3al2lYw5d3YS74ac(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$$ExternalSyntheticLambda9.run(Unknown Source:14)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.networkCallback(SpoofWifiPatch.java:11)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.-$$Nest$smnetworkCallback(Unknown Source:0)
E YouTube : at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.registerDefaultNetworkCallback(SpoofWifiPatch.java:5)
This happens whether WiFi is on but disconnected or off, although it works when WiFi is on and connected.
@aaronjamt Yes, this is what this issue is about.
@oSumAtrIX Do you already have a resolution on how to proceed?
I am not sure. The following works, but it is not practicable, not sure how to proceed.
-keepclassmembernames class ** {
*;
}
The following also works
-keepclassmembernames class ** {
synthetic *** *(...);
}
and restricts it to only synthetic methods at least.
Unfortunately also unpractical, as it would affect all compiler generated methods. It is odd that the wildcard for the class name does not work.
Could I at least create a PR with a workaround for now? You can revert the change when you have found a better solution.
Can the method name be specified as a workaround for now? Make sure, both the code and PR are well documented with all reference which might be required in the future.
I wanted to use this as a workaround:
One way to fix this is to not use a lambda for the fallback, but to return a boolean whether the fallback should run.
Is that ok for you?
Type
Error at runtime
Bug description
Fresh install, first time install. Followed all of the appropriate steps. Android 12 LG Velvet, non-rooted. All recommended versions of APKs, everything that should be up to date is up to date. Patched the youtube apk with all patches except for debugging and hiding certain UI elements. App would consistently black screen for about 20 seconds, then crash. No screen ever appeared. Repeated 6 times. 7th time worked, the only change being that wifi was enabled on the device and connected. adb logs show the following repeated infinitely until the app crashed:
02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.integrations.patches.LithoBlockRegister$$ExternalSyntheticApiModelOutline0.m(Unknown Source:0) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.lambda$registerDefaultNetworkCallback$1(SpoofWifiPatch.java:1) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.$r8$lambda$YPpdCidDTKU3al2lYw5d3YS74ac(Unknown Source:0) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$$ExternalSyntheticLambda9.run(Unknown Source:14) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.networkCallback(SpoofWifiPatch.java:11) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch$Utils.-$$Nest$smnetworkCallback(Unknown Source:0) 02-03 14:51:12.127 23507 23550 E AndroidRuntime: at app.revanced.all.connectivity.wifi.spoof.SpoofWifiPatch.registerDefaultNetworkCallback(SpoofWifiPatch.java:5)
Confirmed issue is with spoof wifi, as the attempted fix was to remove this patch from the patch list, and this has resolved the issue completely.
Steps to reproduce
Follow all of the steps on https://www.reddit.com/r/revancedapp/comments/xlcny9/revanced_manager_guide_for_dummies/ or the official discord guide. Make sure to select spoof wifi patch when selecting patches. Ensure that wifi is disabled on the device, then attempt to launch the app.
Relevant log output
Screenshots or videos
I have video if needed but it's not that interesting since it is a full black screen for 20 seconds then a crash. Please advise if this would be helpful to upload.
Solution
When following the steps from the ReVanced installation guide, make sure to de-select wifi spoofing patch. This resolves the error.
Additional context
Android 12 LG Velvet, non-rooted. All recommended versions of APKs, everything that should be up to date is up to date.
Acknowledgements