Chest Tracker

Chest Tracker

355k Downloads

World name containing unmappable characters causes crash.

ShaneTRS opened this issue ยท 5 comments

commented

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.

commented

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.

commented

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.

commented

Here's a screenshot of the realm's name:
image

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

commented

Oversight on my end, wasn't expecting substring to crash if the string wasn't that long. 1.1.6 should work.

commented

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:?]