The bug
You can use the expiration time in banned-players.json
, and the message "Your ban will be removed on xxxxx" shows up fine.
The issue is, it doesn't unban when the time has passed the "expires" time
I banned myself for 1 minute to test it, and I waited about 10 minutes and it still doesn't let me in.
(Just a note, you can't use the expires in the command, only by direct editing the banned-players.json
/ banned-ips.json
file)
banned-ips.json
works fine, you can connect afterwards, but you get an error each first time you try to connect since server restart since expiration date is reached.
Client
Internal Exception: io.netty.handler.codec.DecoderException: java.io.IOException: Bad packet id 26
Server
[21:43:15] [Server thread/WARN]: Failed to handle packet for /IPBLACKEDOUT
0
java.lang.NullPointerException
at mm.a(SourceFile:383) ~[minecraft_server.jar:?]
at md.b(SourceFile:97) ~[minecraft_server.jar:?]
at md.c(SourceFile:62) ~[minecraft_server.jar:?]
at ek.a(SourceFile:232) ~[minecraft_server.jar:?]
at ma.c(SourceFile:187) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.D(SourceFile:643) [minecraft_ser
ver.jar:?]
at la.D(SourceFile:339) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.C(SourceFile:553) [minecraft_ser
ver.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:457) [minecraft_s
erver.jar:?]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_77]
Steps to reproduce (banned-players
)
Run a server
/ban
yourselfClose server
Edit the
banned-players.json
's expiration date to "unban" after 1 minuteStart server again
Wait that time and try to join
Steps to reproduce (banned-ips
)
Run a server
/ban-ip
yourselfClose server
Edit the
banned-ip.json
's expiration date to "unban" after 1 minuteStart server again
Wait that time and try to join, you will receive an error
Try joining again, you'll get in
Close and start the server again
Enter the server, and see the same message again
Code analysis
See this comment.
Linked issues
Attachments
Comments 10
Please link to this comment in the description
The following is based on decompiled version of Minecraft 1.9 using MCP 9.24 beta.
The reason why the entry from the banned-players.json
file is not removed is because the method net.minecraft.server.management.UserList.removeExpired()
uses the wrong key to remove the entry. It uses the value of the entry to remove it, instead it should uses the method net.minecraft.server.management.UserList.getObjectKey(K)
to create the key based on the entry value.
/**
* Removes expired bans from the list. See {@link BanEntry#hasBanExpired}
*/
private void removeExpired()
{
List<K> list = Lists.<K>newArrayList();
for (V v : this.values.values())
{
if (v.hasBanExpired())
{
list.add(v.getValue());
}
}
for (K k : list)
{
// Replaced this
//this.values.remove(k);
this.values.remove(this.getObjectKey(k));
}
}
The reason why an exception is thrown for the first time is because the method net.minecraft.server.management.PlayerList.allowUserToConnect(SocketAddress, GameProfile)
first tests if the GameProfile
is banned and if this is the case it tries to get the ban entry. The problem is that the method net.minecraft.server.management.UserList.getEntry(K)
first removes expired ban entries. This means that it returns null
if the ban was removed, which then causes the NullPointerException
.
Instead the methods net.minecraft.server.management.UserListIPBans.isBanned(SocketAddress)
, net.minecraft.server.management.UserListBans.isBanned(GameProfile)
and net.minecraft.server.management.UserListBans.isUsernameBanned(String)
should remove expired entries first before testing if the IP, GameProfile or username is banned.
Seems to be working fine in 1.13.1
(Yes it unbanned me after)
"created": "2018-08-28 09:34:53 -0400"
"expires": "2018-08-28 09:37:00 -0400"
Please re-open this issue, it's still present in 1.14.4. Reproduction steps are the same - set a ban that will expire, wait until expire time, and then join. The exception will only occur once though.
I have submitted a patch to Paper that Mojang is free to use - https://github.com/PaperMC/Paper/pull/2458
(the code is a bit different due to CraftBukkit changes but the same logic applies)
The relevant code is just this one line (spigot mappings), marked // NPE in PlayerList:
if (this.k.isBanned(gameprofile)) {
GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile);
chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); // NPE
if (gameprofilebanentry.getExpires() != null) {
chatmessage.addSibling(new ChatMessage("multiplayer.disconnect.banned.expiration", new Object[]{PlayerList.g.format(gameprofilebanentry.getExpires())}));
}
the get() call will remove the relevant entry if it has expired, and then return null. Then it will clearly NPE on the marked line.
The stacktrace of this occurring on the vanilla server:
[06:30:45] [Server thread/WARN]: Failed to handle packet for /127.0.0.1:50701
java.lang.NullPointerException: null
at xv.a(SourceFile:357) ~[minecraft_server.jar:?]
at we.c(SourceFile:97) ~[minecraft_server.jar:?]
at we.b(SourceFile:63) ~[minecraft_server.jar:?]
at jc.a(SourceFile:230) ~[minecraft_server.jar:?]
at wb.c(SourceFile:171) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.b(SourceFile:847) [minecraft_server.jar:?]
at uk.b(SourceFile:343) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.a(SourceFile:774) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:642) [minecraft_server.jar:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222]
[06:30:45] [Server thread/INFO]: com.mojang.authlib.GameProfile@664932ca[id=9a9949cc-1987-3d04-b56b-cf3286adfe51,name=searchndstroy,properties={},legacy=false] (/127.0.0.1:50701) lost connection: Internal server error
@unknown, could you please create a new ticket that we can mark as a clone of this ticket? I'd rather have a new ticket than reusing this one.
Can confirm (See attached picture img.png)