Add exception-resilience to reading UUID. Fixes BUKKIT-4833

When a "uid.dat" file is corrupt (empty or <16 bytes), WorldNBTStorage
will silently fail to read and return null. Non-null behavior is
expected everywhere that this value is used.

This change will force a random UUID when the previous UUID cannot be
read, and getUUID to no longer silently ignore read/write exceptions.
This commit is contained in:
Wesley Wolfe 2013-10-06 22:37:44 -05:00
parent cfa5490a58
commit ca5e0c6db0

View File

@ -8,7 +8,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Logger;
// CraftBukkit start
import java.util.UUID;
@ -247,26 +246,43 @@ public class WorldNBTStorage implements IDataManager, IPlayerFileData {
// CraftBukkit start
public UUID getUUID() {
if (uuid != null) return uuid;
try {
File file1 = new File(this.baseDir, "uid.dat");
if (!file1.exists()) {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file1));
if (file1.exists()) {
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream(file1));
return uuid = new UUID(dis.readLong(), dis.readLong());
} catch (IOException ex) {
MinecraftServer.getServer().getLogger().severe("Failed to read " + file1 + ", generating new random UUID", ex);
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException ex) {
// NOOP
}
}
}
}
uuid = UUID.randomUUID();
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(file1));
dos.writeLong(uuid.getMostSignificantBits());
dos.writeLong(uuid.getLeastSignificantBits());
} catch (IOException ex) {
MinecraftServer.getServer().getLogger().severe("Failed to write " + file1, ex);
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException ex) {
// NOOP
}
}
else {
DataInputStream dis = new DataInputStream(new FileInputStream(file1));
uuid = new UUID(dis.readLong(), dis.readLong());
dis.close();
}
return uuid;
}
catch (IOException ex) {
return null;
}
}
public File getPlayerDir() {
return playerDir;