make sure there is an exception if the file is corrupt

This commit is contained in:
2017-04-17 17:52:11 +02:00
parent bcb2e6ca83
commit c58e7baf69
3 changed files with 49 additions and 9 deletions

View File

@@ -13,9 +13,9 @@ enum ByteType {
VERSION(1);// 00000001 VERSION(1);// 00000001
interface ContinuationByte { interface ContinuationByte {
long NUMBER_OF_VALUES_BITS = 7; int NUMBER_OF_VALUES_BITS = 7;
long CONTINUATION_BYTE_PREFIX = 1 << NUMBER_OF_VALUES_BITS; // 10000000 int CONTINUATION_BYTE_PREFIX = 1 << NUMBER_OF_VALUES_BITS; // 10000000
} }
interface VersionByte { interface VersionByte {
@@ -24,19 +24,23 @@ enum ByteType {
* which cannot hold any value (unless it is 0). And the second byte is * which cannot hold any value (unless it is 0). And the second byte is
* the actual value. * the actual value.
*/ */
long MIN_LENGTH = 2; int MIN_LENGTH = 2;
} }
private final long firstBytePrefix; private final int firstBytePrefix;
private ByteType(final long firstBytePrefix) { private ByteType(final int firstBytePrefix) {
this.firstBytePrefix = firstBytePrefix; this.firstBytePrefix = firstBytePrefix;
} }
public long getBytePrefix() { public int getBytePrefix() {
return firstBytePrefix; return firstBytePrefix;
} }
public byte getBytePrefixAsByte() {
return (byte) firstBytePrefix;
}
/** /**
* the max value for the first byte is the prefix minus 1, because prefixes * the max value for the first byte is the prefix minus 1, because prefixes
* start with 0⋯010⋯0, so prefix -1 is 0⋯01⋯1 which is exactly the max value * start with 0⋯010⋯0, so prefix -1 is 0⋯01⋯1 which is exactly the max value
@@ -53,7 +57,7 @@ enum ByteType {
* *
* @return bitmap with the value bits set * @return bitmap with the value bits set
*/ */
public long getValueBits() { public int getValueBits() {
return firstBytePrefix - 1; return firstBytePrefix - 1;
} }
@@ -64,7 +68,7 @@ enum ByteType {
return firstBytePrefix == (theByte & prefixBits); return firstBytePrefix == (theByte & prefixBits);
} }
public long getPrefixBits() { public int getPrefixBits() {
return (~getValueBits()) & 0xff; return (~getValueBits()) & 0xff;
} }
@@ -78,7 +82,7 @@ enum ByteType {
return null; return null;
} }
public long getValue(final int aByte) { public int getValue(final int aByte) {
return aByte & getValueBits(); return aByte & getValueBits();
} }
} }

View File

@@ -90,6 +90,7 @@ class PdbReader implements AutoCloseable {
} }
Entry readNullableEntry() throws ReadRuntimeException { Entry readNullableEntry() throws ReadRuntimeException {
try { try {
final long epochMilliIncrement = readValue(ByteType.DATE_INCREMENT); final long epochMilliIncrement = readValue(ByteType.DATE_INCREMENT);
if (epochMilliIncrement < 0) { if (epochMilliIncrement < 0) {
@@ -127,6 +128,7 @@ class PdbReader implements AutoCloseable {
if (!byteType.isValid(firstByte)) { if (!byteType.isValid(firstByte)) {
if (firstByte < 0) { if (firstByte < 0) {
// end of file reached
return -1; return -1;
} else if (ByteType.DATE_OFFSET.isValid(firstByte)) { } else if (ByteType.DATE_OFFSET.isValid(firstByte)) {
final long dateOffsetInit = firstByte & ByteType.DATE_OFFSET.getValueBits(); final long dateOffsetInit = firstByte & ByteType.DATE_OFFSET.getValueBits();

View File

@@ -4,6 +4,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.Instant; import java.time.Instant;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneId; import java.time.ZoneId;
@@ -88,6 +89,39 @@ public class PdbReaderWriterTest {
Assert.assertEquals(actual, entry); Assert.assertEquals(actual, entry);
} }
reader.readEntry().ifPresent(e -> {
throw new AssertionError();
});
}
}
@Test(expectedExceptions = FileCorruptException.class)
public void testReadExceptionOnCorruptEntries() throws Exception {
final Entry entryA = new Entry(1, 1, TAGS);
final File file = Files.createTempFile(dataDirectory, "pdb", ".db").toFile();
final PdbFile pdbFile = new PdbFile(file.toPath(), TAGS);
try (PdbWriter writer = new PdbWriter(pdbFile)) {
writer.write(entryA);
}
// make the file corrupt
// two date consecutive increments will never happen in valid data
final byte[] corruptEntries = new byte[] { //
ByteType.DATE_INCREMENT.getBytePrefixAsByte(), //
ByteType.DATE_INCREMENT.getBytePrefixAsByte() //
};
Files.write(file.toPath(), corruptEntries, StandardOpenOption.APPEND);
try (final PdbReader reader = new PdbReader(pdbFile)) {
final Entry actualA = reader.readEntry().orElseThrow(() -> new AssertionError());
Assert.assertEquals(actualA, entryA);
reader.readEntry(); // should throw FileCorruptException
} }
} }
} }