Fixed NPE in MDF4ProcessWriter#fillRecordArray NPE is caused by wrongly reading an UINT8 as INT8. The error is in MDF4Util#readUInt8 which is called by multiple other locations in the code. Fixing the method required changing the return type, which led to changes in various *BLOCKs. Change-Id: I62754f19e940d08143c57230b787c219f72ab3e8 Signed-off-by: Matthias Koller <m.koller@peak-solution.de>
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CCBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CCBLOCK.java index f51a798..edaa1d9 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CCBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CCBLOCK.java
@@ -48,7 +48,7 @@ // 9 = text to value tabular look-up // 10 = text to text tabular look-up (translation) // UINT8 - private byte type; + private int type; // Precision for display of floating point values. // 0xFF means unrestricted precision (infinite) @@ -58,7 +58,7 @@ // cn_precision of the parent CNBLOCK is invalid, // otherwise cn_precision must be used. // UINT8 - private byte precision; + private int precision; // Flags // The value contains the following bit flags (Bit 0 = LSB): @@ -138,11 +138,11 @@ return ret; } - public byte getType() { + public int getType() { return type; } - public byte getPrecision() { + public int getPrecision() { return precision; } @@ -170,11 +170,11 @@ return val; } - private void setType(byte type) { + private void setType(int type) { this.type = type; } - private void setPrecision(byte precision) { + private void setPrecision(int precision) { this.precision = precision; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CHBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CHBLOCK.java index e4ef657..d91b6ac 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CHBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/CHBLOCK.java
@@ -59,7 +59,7 @@ /** * Type of the hierachy this CHBLOCK maintaines. */ - private byte hirarchyType; + private int hirarchyType; // Getters and Setters // Link to next CHBLOCK @@ -101,11 +101,11 @@ this.elementCount = elementCount; } - public byte getHirarchyType() { + public int getHirarchyType() { return hirarchyType; } - public void setHirarchyType(byte hirarchyType) { + public void setHirarchyType(int hirarchyType) { this.hirarchyType = hirarchyType; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DGBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DGBLOCK.java index 8964aec..58ff9d6 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DGBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DGBLOCK.java
@@ -36,7 +36,7 @@ // 4 = record ID (UINT32, LE Byte order) before each data record // 8 = record ID (UINT64, LE Byte order) before each data record // UINT8 - private byte recIdSize; + private int recIdSize; /** * Parse a HLBLOCK from an existing MDFGenBlock @@ -78,11 +78,11 @@ return links[3]; } - public byte getRecIdSize() { + public int getRecIdSize() { return recIdSize; } - public void setRecIdSize(byte recIdSize) { + public void setRecIdSize(int recIdSize) { this.recIdSize = recIdSize; } @@ -112,7 +112,7 @@ public byte[] getBodyBytes() { // UINT8: Number of Bytes used for record IDs in the data block. byte[] ret = new byte[8]; - ret[0] = getRecIdSize(); + ret[0] = MDF4Util.toUInt8(getRecIdSize()); return ret; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DLBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DLBLOCK.java index dc6d0f3..b2b01bc 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DLBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DLBLOCK.java
@@ -40,7 +40,7 @@ // Flags // Bit 0: Equal length flag // UINT8 - private byte flags; + private int flags; // Number of referenced blocks N // UINT32 @@ -84,7 +84,7 @@ return Arrays.copyOfRange(links, 1, links.length); } - public byte getFlags() { + public int getFlags() { return flags; } @@ -100,7 +100,7 @@ return offset; } - public void setFlags(byte flags) { + public void setFlags(int flags) { this.flags = flags; } @@ -162,7 +162,7 @@ byte[] ret = new byte[arraylen]; // flags UINT8 - ret[0] = flags; + ret[0] = MDF4Util.toUInt8(flags); byte[] count = MDF4Util.getBytesUInt32(this.count); System.arraycopy(count, 0, ret, 4, 4);
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DZBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DZBLOCK.java index 3812268..c2034de 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DZBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/DZBLOCK.java
@@ -37,7 +37,7 @@ // Zip algorithm used to compress the data (0=Deflate; 1=Transpose and // Deflate) // UINT8 - private byte zip_type; + private int zip_type; // Parameters for zip algorithm // UINT32 @@ -82,11 +82,11 @@ this.block_type = block_type; } - public byte getZip_type() { + public int getZip_type() { return zip_type; } - public void setZip_type(byte zip_type) { + public void setZip_type(int zip_type) { this.zip_type = zip_type; } @@ -146,7 +146,7 @@ byte[] type = MDF4Util.getBytesCharsUTF8(getBlock_type()); System.arraycopy(type, 0, ret, 0, 2); - ret[3] = zip_type; + ret[3] = MDF4Util.toUInt8(zip_type); byte[] zipparam = MDF4Util.getBytesUInt32(zip_parameters); System.arraycopy(zipparam, 0, ret, 4, 4);
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/FHBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/FHBLOCK.java index 20b8d28..c9276fc 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/FHBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/FHBLOCK.java
@@ -42,7 +42,7 @@ // Time flags Bit 0: Local Time flag / Bit 1: Time offset valid flag // UINT8 - private byte time_flags; + private int time_flags; /** * Constructor @@ -93,11 +93,11 @@ this.dst_offset_min = dst_offset_min; } - public byte getTime_flags() { + public int getTime_flags() { return time_flags; } - public void setTime_flags(byte time_flags) { + public void setTime_flags(int time_flags) { this.time_flags = time_flags; } @@ -124,7 +124,7 @@ byte[] dst_offset = MDF4Util.getBytesInt16(getDst_offset_min()); System.arraycopy(dst_offset, 0, ret, 10, 2); - ret[11] = time_flags; + ret[11] = MDF4Util.toUInt8(time_flags); return ret; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HDBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HDBLOCK.java index 136dddb..4f8e70b 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HDBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HDBLOCK.java
@@ -75,14 +75,14 @@ // (after conversion of offsets to ns) by // Local time = UTC time + time zone offset + DST offset. // UINT8 - private byte timeFlags; + private int timeFlags; // Time quality class // 0 = local PC reference time (Default) // 10 = external time source // 16 = external absolute synchronized time // UINT8 - private byte timeClass; + private int timeClass; // Flags // The value contains the following bit flags (Bit 0 = LSB): @@ -91,7 +91,7 @@ // Bit 1: Start distance valid flag. If set, the start distance value below // is valid. // UINT8 - private byte flags; + private int flags; // Start angle in radians at start of measurement (only for angle // synchronous measurements) @@ -169,27 +169,27 @@ this.dstOffsetMin = dstOffsetMin; } - public byte getTimeFlags() { + public int getTimeFlags() { return timeFlags; } - private void setTimeFlags(byte timeFlags) { + private void setTimeFlags(int timeFlags) { this.timeFlags = timeFlags; } - public byte getTimeClass() { + public int getTimeClass() { return timeClass; } - private void setTimeClass(byte timeClass) { + private void setTimeClass(int timeClass) { this.timeClass = timeClass; } - public byte getFlags() { + public int getFlags() { return flags; } - private void setFlags(byte flags) { + private void setFlags(int flags) { this.flags = flags; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HLBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HLBLOCK.java index 3338407..9635124 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HLBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/HLBLOCK.java
@@ -38,7 +38,7 @@ // Zip algorithm used to compress the data (0=Deflate; 1=Transpose and // Deflate) // UINT8 - private byte ziptype; + private int ziptype; public HLBLOCK() { super(0); @@ -70,11 +70,11 @@ this.flags = flags; } - public byte getZiptype() { + public int getZiptype() { return ziptype; } - public void setZiptype(byte ziptype) { + public void setZiptype(int ziptype) { this.ziptype = ziptype; } @@ -101,7 +101,7 @@ byte[] hl_flags = MDF4Util.getBytesUInt16(flags); System.arraycopy(hl_flags, 0, ret, 0, 2); - ret[3] = ziptype; + ret[3] = MDF4Util.toUInt8(ziptype); return ret; }
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4ProcessWriter.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4ProcessWriter.java index 08131a5..c6668ea 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4ProcessWriter.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4ProcessWriter.java
@@ -437,7 +437,7 @@ int[] recCounters = new int[groups.size()]; - byte idSize = datagroup.getRecIdSize(); + int idSize = datagroup.getRecIdSize(); int i = 0; Map<Long, Integer> recNumtoArrIdx = new HashMap<Long, Integer>();
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4Util.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4Util.java index 6618302..bad025e 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4Util.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/MDF4Util.java
@@ -47,21 +47,36 @@ * The byte buffer. * @return The value. */ - public static byte readUInt8(ByteBuffer bb) { + public static byte readInt8(ByteBuffer bb) { return bb.order(ByteOrder.LITTLE_ENDIAN).get(); } /** - * Read an 8-bit signed integer from the byte buffer. + * Read an 8-bit unsigned integer from the byte buffer. * * @param bb * The byte buffer. * @return The value. */ - public static int readInt8(ByteBuffer bb) { + public static int readUInt8(ByteBuffer bb) { return bb.order(ByteOrder.LITTLE_ENDIAN).get() & 0xff; } + /** + * Convert an integer to a UINT8 byte + * + * @param uint value as int + * @return byte representing the uint8 + * @throws IllegalArgumentException if the value is out of range [0, 255] + */ + public static byte toUInt8(int uint) { + if (uint >= 0 && uint < 256) { + return (byte) (uint & 0xff); + } else { + throw new IllegalArgumentException(uint + " cannot be converted to UINT8."); + } + } + /** * Read an 16-bit unsigned integer from the byte buffer. *
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/SIBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/SIBLOCK.java index 3106210..73502fc 100644 --- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/SIBLOCK.java +++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf4/SIBLOCK.java
@@ -42,7 +42,7 @@ // 5 = USER source is a user interaction/input // (e.g. for user generated events) // UINT8 - private byte sourceType; + private int sourceType; // Bus type: additional classification of used bus (should be 0 for si_type // ≥ 3): @@ -57,7 +57,7 @@ // 8 = USB // Vender defined bus types can be added starting with value 128. // UINT8 - private byte busType; + private int busType; // Flags // The value contains the following bit flags (Bit 0 = LSB): @@ -65,7 +65,7 @@ // Source is only a simulation (can be hardware or software simulated) // Cannot be set for si_type = 4 (TOOL). // UINT8 - private byte flags; + private int flags; /** * Parse a SIBLOCK from an existing MDFGenBlock @@ -82,15 +82,15 @@ parent.setPrec(this); } - private void setSourceType(byte sourceType) { + private void setSourceType(int sourceType) { this.sourceType = sourceType; } - private void setBusType(byte busType) { + private void setBusType(int busType) { this.busType = busType; } - private void setFlags(byte flags) { + private void setFlags(int flags) { this.flags = flags; } @@ -106,15 +106,15 @@ return links[2]; } - public byte getSourceType() { + public int getSourceType() { return sourceType; } - public byte getBusType() { + public int getBusType() { return busType; } - public byte getFlags() { + public int getFlags() { return flags; }
diff --git a/src/test/java/org/eclipse/mdm/mdfsorter/MDF4UtilTest.java b/src/test/java/org/eclipse/mdm/mdfsorter/MDF4UtilTest.java index f4fdbee..4748c0b 100644 --- a/src/test/java/org/eclipse/mdm/mdfsorter/MDF4UtilTest.java +++ b/src/test/java/org/eclipse/mdm/mdfsorter/MDF4UtilTest.java
@@ -16,6 +16,10 @@ package org.eclipse.mdm.mdfsorter; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.nio.ByteBuffer; import org.eclipse.mdm.mdfsorter.mdf4.MDF4Util; import org.junit.AfterClass; @@ -33,6 +37,51 @@ } @Test + public void testReadUInt8() { + ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 1, 127, -128, -1 }); + + assertEquals(MDF4Util.readUInt8(bb), 0); + assertEquals(MDF4Util.readUInt8(bb), 1); + assertEquals(MDF4Util.readUInt8(bb), 127); + assertEquals(MDF4Util.readUInt8(bb), 128); + assertEquals(MDF4Util.readUInt8(bb), 255); + } + + @Test + public void testToUInt8() { + assertEquals(MDF4Util.toUInt8(0), 0); + assertEquals(MDF4Util.toUInt8(1), 1); + assertEquals(MDF4Util.toUInt8(127), 127); + assertEquals(MDF4Util.toUInt8(128), -128); + assertEquals(MDF4Util.toUInt8(255), -1); + + try { + MDF4Util.toUInt8(256); + fail("Should throw an exception!"); + } catch (IllegalArgumentException e) { + assertEquals(e.getMessage(), "256 cannot be converted to UINT8."); + } + + try { + MDF4Util.toUInt8(-1); + fail("Should throw an exception!"); + } catch (IllegalArgumentException e) { + assertEquals(e.getMessage(), "-1 cannot be converted to UINT8."); + } + } + + @Test + public void testReadInt8() { + ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 1, 127, -128, -1 }); + + assertEquals(MDF4Util.readInt8(bb), 0); + assertEquals(MDF4Util.readInt8(bb), 1); + assertEquals(MDF4Util.readInt8(bb), 127); + assertEquals(MDF4Util.readInt8(bb), -128); + assertEquals(MDF4Util.readInt8(bb), -1); + } + + @Test public void testGetBytesUInt32() { long l = Integer.MAX_VALUE * 2L + 1L; assertArrayEquals(MDF4Util.getBytesUInt32(l), new byte[] { -1, -1, -1, -1 });