World name containing unmappable characters causes crash.
ShaneTRS opened this issue ยท 5 comments
To Reproduce
Join a realm with a name that has unmappable characters.
Crash Report
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: realms-AlwaysInTreble-? ? ? ? ? ? ? ? ? ? ?.json
at sun.nio.fs.UnixPath.encode(UnixPath.java:121) ~[?:?]
at sun.nio.fs.UnixPath.<init>(UnixPath.java:68) ~[?:?]
at sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:279) ~[?:?]
at java.nio.file.Path.resolve(Path.java:515) ~[?:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getFilePath(MemoryDatabase.java:160) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.load(MemoryDatabase.java:115) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getCurrent(MemoryDatabase.java:62) ~[chesttracker.jar:?]
at net.minecraft.class_2535.handler$znk000$chestTracker$onDisconnectHandler(class_2535.java:519) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.method_10747(class_2535.java) ~[client-intermediary.jar:?]
at fudge.notenoughcrashes.mixinhandlers.InGameCatcher.cleanupBeforeMinecraft(InGameCatcher.java:51) ~[notenoughcrashes.jar:?]
at net.minecraft.class_310.handler$doo000$beforeCleanUpAfterCrash(class_310.java:23058) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1519(class_310.java) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1514(class_310.java:759) ~[client-intermediary.jar:?]
at net.minecraft.client.main.Main.main(Main.java:238) [client-intermediary.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:602) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.12.11.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.multimc.onesix.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:210) [NewLaunch.jar:?]
at org.multimc.onesix.OneSixLauncher.launch(OneSixLauncher.java:245) [NewLaunch.jar:?]
at org.multimc.EntryPoint.listen(EntryPoint.java:143) [NewLaunch.jar:?]
at org.multimc.EntryPoint.main(EntryPoint.java:34) [NewLaunch.jar:?]
Additional context
https://github.com/JackFred2/ChestTracker/blob/master/src/main/java/red/jackf/chesttracker/memory/MemoryDatabase.java#L79
MemoryUtils.makeFileSafe
doesn't seem to be making it safe enough
Personally, I wouldn't use world names directly in the file-name, hashing it or taking base64 would be my go-to.
This crash is specifically for a realm, but I'm sure it happens with any world.
Not entirely sure the cleanest way to solve this at the moment as it seems to be something beyond my control, so I'm going to add an "ultra-safe" file name sanitiser which doesn't allow any non-alphanumeric + safe symbol characters. You may have to rename a database file to restore data when the option is changed. Sorry for the hastle + wait.
Thanks for the report, I haven't been able to test realms properly.
I do want to keep the files sort-of identifiable, so what I'll do is have a character whitelist instead of blacklist which should give a mostly safe filename, and shouldn't break most existing names.
Out of interest, can you copy-paste (or screenshot if you can't) the name of the realms server, or the characters that are causing issues? They haven't come through on the crash report and I'd like to make sure the fix works properly.
Here's a screenshot of the realm's name:
Based on that, I'm sure the list of invalid characters is pretty extensive. A whitelist is a good idea.
I did end up trying your fix that you posted on Modrinth, and unfortunately it seems to implement a different crash that occurs in all multiplayer worlds.
java.lang.StringIndexOutOfBoundsException: begin 0, end 180, length 38
at java.lang.String.checkBoundsBeginEnd(String.java:4601) ~[?:?]
at java.lang.String.substring(String.java:2704) ~[?:?]
at red.jackf.chesttracker.memory.MemoryUtils.makeFileSafe(MemoryUtils.java:186) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getUsableId(MemoryDatabase.java:79) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getCurrent(MemoryDatabase.java:58) ~[chesttracker.jar:?]
at red.jackf.chesttracker.ChestTracker.drawLabels(ChestTracker.java:119) ~[chesttracker.jar:?]
at net.minecraft.class_761.handler$bmg000$afterEntities(class_761.java:7953) ~[client-intermediary.jar:?]
at net.minecraft.class_761.method_22710(class_761.java:1337) ~[client-intermediary.jar:?]
at net.minecraft.class_757.method_3188(class_757.java:1031) ~[client-intermediary.jar:?]
at net.minecraft.class_757.method_3192(class_757.java:811) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1523(class_310.java:1117) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1514(class_310.java:733) [client-intermediary.jar:?]
at net.minecraft.client.main.Main.main(Main.java:238) [client-intermediary.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:602) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.12.11.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.multimc.onesix.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:210) [NewLaunch.jar:?]
at org.multimc.onesix.OneSixLauncher.launch(OneSixLauncher.java:245) [NewLaunch.jar:?]
at org.multimc.EntryPoint.listen(EntryPoint.java:143) [NewLaunch.jar:?]
at org.multimc.EntryPoint.main(EntryPoint.java:34) [NewLaunch.jar:?]
[11:38:13] [Render thread/ERROR]: Unhandled game exception
java.lang.StringIndexOutOfBoundsException: begin 0, end 180, length 38
at java.lang.String.checkBoundsBeginEnd(String.java:4601) ~[?:?]
at java.lang.String.substring(String.java:2704) ~[?:?]
at red.jackf.chesttracker.memory.MemoryUtils.makeFileSafe(MemoryUtils.java:186) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getUsableId(MemoryDatabase.java:79) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getCurrent(MemoryDatabase.java:58) ~[chesttracker.jar:?]
at net.minecraft.class_2535.handler$znk000$chestTracker$onDisconnectHandler(class_2535.java:519) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.method_10747(class_2535.java) ~[client-intermediary.jar:?]
at fudge.notenoughcrashes.mixinhandlers.InGameCatcher.cleanupBeforeMinecraft(InGameCatcher.java:51) ~[notenoughcrashes.jar:?]
at net.minecraft.class_310.handler$doo000$beforeCleanUpAfterCrash(class_310.java:23058) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1519(class_310.java) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1514(class_310.java:759) ~[client-intermediary.jar:?]
at net.minecraft.client.main.Main.main(Main.java:238) [client-intermediary.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:602) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77) [fabric-loader-0.12.11.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.12.11.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.multimc.onesix.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:210) [NewLaunch.jar:?]
at org.multimc.onesix.OneSixLauncher.launch(OneSixLauncher.java:245) [NewLaunch.jar:?]
at org.multimc.EntryPoint.listen(EntryPoint.java:143) [NewLaunch.jar:?]
at org.multimc.EntryPoint.main(EntryPoint.java:34) [NewLaunch.jar:?]
Just glancing at the code makes it seem like an easy fix.
https://github.com/JackFred2/ChestTracker/blob/master/src/main/java/red/jackf/chesttracker/memory/MemoryUtils.java#L186
Oversight on my end, wasn't expecting substring to crash if the string wasn't that long. 1.1.6 should work.
I thought it was working, but apparently I didn't test it afterwards.
I still get a crash when joining the realm with 1.1.6.
[19:56:43] [Render thread/FATAL]: Unreported exception thrown!
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: realms-AlwaysInTreble_? ? ? ? ? ? ? ? ? ? ?.json
at sun.nio.fs.UnixPath.encode(UnixPath.java:121) ~[?:?]
at sun.nio.fs.UnixPath.<init>(UnixPath.java:68) ~[?:?]
at sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:279) ~[?:?]
at java.nio.file.Path.resolve(Path.java:515) ~[?:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getFilePath(MemoryDatabase.java:160) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.load(MemoryDatabase.java:115) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getCurrent(MemoryDatabase.java:62) ~[chesttracker.jar:?]
at red.jackf.chesttracker.ChestTracker.drawLabels(ChestTracker.java:119) ~[chesttracker.jar:?]
at net.minecraft.class_761.handler$bmj000$afterEntities(class_761.java:7953) ~[client-intermediary.jar:?]
at net.minecraft.class_761.method_22710(class_761.java:1337) ~[client-intermediary.jar:?]
at net.minecraft.class_757.method_3188(class_757.java:1031) ~[client-intermediary.jar:?]
at net.minecraft.class_757.method_3192(class_757.java:811) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1523(class_310.java:1117) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1514(class_310.java:733) [client-intermediary.jar:?]
at net.minecraft.client.main.Main.main(Main.java:238) [client-intermediary.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:608) [fabric-loader-0.12.12.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77) [fabric-loader-0.12.12.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.12.12.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.multimc.onesix.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:210) [NewLaunch.jar:?]
at org.multimc.onesix.OneSixLauncher.launch(OneSixLauncher.java:245) [NewLaunch.jar:?]
at org.multimc.EntryPoint.listen(EntryPoint.java:143) [NewLaunch.jar:?]
at org.multimc.EntryPoint.main(EntryPoint.java:34) [NewLaunch.jar:?]
[19:56:43] [Render thread/ERROR]: Unhandled game exception
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: realms-AlwaysInTreble_? ? ? ? ? ? ? ? ? ? ?.json
at sun.nio.fs.UnixPath.encode(UnixPath.java:121) ~[?:?]
at sun.nio.fs.UnixPath.<init>(UnixPath.java:68) ~[?:?]
at sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:279) ~[?:?]
at java.nio.file.Path.resolve(Path.java:515) ~[?:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getFilePath(MemoryDatabase.java:160) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.load(MemoryDatabase.java:115) ~[chesttracker.jar:?]
at red.jackf.chesttracker.memory.MemoryDatabase.getCurrent(MemoryDatabase.java:62) ~[chesttracker.jar:?]
at net.minecraft.class_2535.handler$znk000$chestTracker$onDisconnectHandler(class_2535.java:519) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.method_10747(class_2535.java) ~[client-intermediary.jar:?]
at fudge.notenoughcrashes.mixinhandlers.InGameCatcher.cleanupBeforeMinecraft(InGameCatcher.java:51) ~[notenoughcrashes.jar:?]
at net.minecraft.class_310.handler$ebk000$beforeCleanUpAfterCrash(class_310.java:23058) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1519(class_310.java) ~[client-intermediary.jar:?]
at net.minecraft.class_310.method_1514(class_310.java:759) ~[client-intermediary.jar:?]
at net.minecraft.client.main.Main.main(Main.java:238) [client-intermediary.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:608) [fabric-loader-0.12.12.jar:?]
at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:77) [fabric-loader-0.12.12.jar:?]
at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23) [fabric-loader-0.12.12.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.multimc.onesix.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:210) [NewLaunch.jar:?]
at org.multimc.onesix.OneSixLauncher.launch(OneSixLauncher.java:245) [NewLaunch.jar:?]
at org.multimc.EntryPoint.listen(EntryPoint.java:143) [NewLaunch.jar:?]
at org.multimc.EntryPoint.main(EntryPoint.java:34) [NewLaunch.jar:?]