diff --git a/performanceDb/src/main/java/org/lucares/performance/db/ByteType.java b/performanceDb/src/main/java/org/lucares/performance/db/ByteType.java index cbe693e..bb5eacc 100644 --- a/performanceDb/src/main/java/org/lucares/performance/db/ByteType.java +++ b/performanceDb/src/main/java/org/lucares/performance/db/ByteType.java @@ -13,9 +13,9 @@ enum ByteType { VERSION(1);// 00000001 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 { @@ -24,19 +24,23 @@ enum ByteType { * which cannot hold any value (unless it is 0). And the second byte is * 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; } - public long getBytePrefix() { + public int getBytePrefix() { return firstBytePrefix; } + public byte getBytePrefixAsByte() { + return (byte) firstBytePrefix; + } + /** * 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 @@ -53,7 +57,7 @@ enum ByteType { * * @return bitmap with the value bits set */ - public long getValueBits() { + public int getValueBits() { return firstBytePrefix - 1; } @@ -64,7 +68,7 @@ enum ByteType { return firstBytePrefix == (theByte & prefixBits); } - public long getPrefixBits() { + public int getPrefixBits() { return (~getValueBits()) & 0xff; } @@ -78,7 +82,7 @@ enum ByteType { return null; } - public long getValue(final int aByte) { + public int getValue(final int aByte) { return aByte & getValueBits(); } } diff --git a/performanceDb/src/main/java/org/lucares/performance/db/PdbReader.java b/performanceDb/src/main/java/org/lucares/performance/db/PdbReader.java index b4ea080..3f51deb 100644 --- a/performanceDb/src/main/java/org/lucares/performance/db/PdbReader.java +++ b/performanceDb/src/main/java/org/lucares/performance/db/PdbReader.java @@ -90,6 +90,7 @@ class PdbReader implements AutoCloseable { } Entry readNullableEntry() throws ReadRuntimeException { + try { final long epochMilliIncrement = readValue(ByteType.DATE_INCREMENT); if (epochMilliIncrement < 0) { @@ -127,6 +128,7 @@ class PdbReader implements AutoCloseable { if (!byteType.isValid(firstByte)) { if (firstByte < 0) { + // end of file reached return -1; } else if (ByteType.DATE_OFFSET.isValid(firstByte)) { final long dateOffsetInit = firstByte & ByteType.DATE_OFFSET.getValueBits(); diff --git a/performanceDb/src/test/java/org/lucares/performance/db/PdbReaderWriterTest.java b/performanceDb/src/test/java/org/lucares/performance/db/PdbReaderWriterTest.java index e531172..f431255 100644 --- a/performanceDb/src/test/java/org/lucares/performance/db/PdbReaderWriterTest.java +++ b/performanceDb/src/test/java/org/lucares/performance/db/PdbReaderWriterTest.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneId; @@ -88,6 +89,39 @@ public class PdbReaderWriterTest { 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 } } }