We now generate an adler32 checksum for each patched file and verify at load time that they match.

Mismatch won't crash, but will emit a big warning..
This commit is contained in:
Christian 2013-07-08 13:19:14 -04:00
parent 94315253b1
commit e64c07a109
3 changed files with 24 additions and 2 deletions

View file

@ -6,12 +6,14 @@ public class ClassPatch {
public final String targetClassName; public final String targetClassName;
public final boolean existsAtTarget; public final boolean existsAtTarget;
public final byte[] patch; public final byte[] patch;
public ClassPatch(String name, String sourceClassName, String targetClassName, boolean existsAtTarget, byte[] patch) public final int inputChecksum;
public ClassPatch(String name, String sourceClassName, String targetClassName, boolean existsAtTarget, int inputChecksum, byte[] patch)
{ {
this.name = name; this.name = name;
this.sourceClassName = sourceClassName; this.sourceClassName = sourceClassName;
this.targetClassName = targetClassName; this.targetClassName = targetClassName;
this.existsAtTarget = existsAtTarget; this.existsAtTarget = existsAtTarget;
this.inputChecksum = inputChecksum;
this.patch = patch; this.patch = patch;
} }

View file

@ -26,6 +26,7 @@ import com.google.common.base.Strings;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Files; import com.google.common.io.Files;
@ -80,6 +81,14 @@ public class ClassPatchManager {
{ {
FMLLog.warning("Patcher expecting empty class data file for %s, but received non-empty", patch.targetClassName); FMLLog.warning("Patcher expecting empty class data file for %s, but received non-empty", patch.targetClassName);
} }
else
{
int inputChecksum = Hashing.adler32().hashBytes(inputData).asInt();
if (patch.inputChecksum != inputChecksum)
{
FMLLog.severe("There is a binary discrepency between the expected input class %s (%s) and the actual class. Checksum on disk is %x, in patch %x. Things are probably about to go very wrong. Did you put something into the jar file?", mappedName, name, inputChecksum, patch.inputChecksum);
}
}
synchronized (patcher) synchronized (patcher)
{ {
try try
@ -181,10 +190,15 @@ public class ClassPatchManager {
String sourceClassName = input.readUTF(); String sourceClassName = input.readUTF();
String targetClassName = input.readUTF(); String targetClassName = input.readUTF();
boolean exists = input.readBoolean(); boolean exists = input.readBoolean();
int inputChecksum = 0;
if (exists)
{
inputChecksum = input.readInt();
}
int patchLength = input.readInt(); int patchLength = input.readInt();
byte[] patchBytes = new byte[patchLength]; byte[] patchBytes = new byte[patchLength];
input.readFully(patchBytes); input.readFully(patchBytes);
return new ClassPatch(name, sourceClassName, targetClassName, exists, patchBytes); return new ClassPatch(name, sourceClassName, targetClassName, exists, inputChecksum, patchBytes);
} }
} }

View file

@ -13,6 +13,7 @@ import java.util.logging.Logger;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Files; import com.google.common.io.Files;
@ -64,6 +65,7 @@ public class GenDiffSet {
byte[] diff = delta.compute(vanillaBytes, patchedBytes); byte[] diff = delta.compute(vanillaBytes, patchedBytes);
ByteArrayDataOutput diffOut = ByteStreams.newDataOutput(diff.length + 50); ByteArrayDataOutput diffOut = ByteStreams.newDataOutput(diff.length + 50);
// Original name // Original name
diffOut.writeUTF(name); diffOut.writeUTF(name);
@ -73,6 +75,10 @@ public class GenDiffSet {
diffOut.writeUTF(targetClassName); diffOut.writeUTF(targetClassName);
// exists at original // exists at original
diffOut.writeBoolean(entry != null); diffOut.writeBoolean(entry != null);
if (entry != null)
{
diffOut.writeInt(Hashing.adler32().hashBytes(vanillaBytes).asInt());
}
// length of patch // length of patch
diffOut.writeInt(diff.length); diffOut.writeInt(diff.length);
// patch // patch