You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2021/04/20 06:26:38 UTC

svn commit: r1888997 - in /pdfbox/trunk/fontbox/src: main/java/org/apache/fontbox/cff/DataInput.java test/java/org/apache/fontbox/cff/DataInputTest.java

Author: lehmi
Date: Tue Apr 20 06:26:38 2021
New Revision: 1888997

URL: http://svn.apache.org/viewvc?rev=1888997&view=rev
Log:
PDFBOX-5143: don't use unchecked exceptions, add more checks, add tests

Added:
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java   (with props)
Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java?rev=1888997&r1=1888996&r2=1888997&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java Tue Apr 20 06:26:38 2021
@@ -16,12 +16,7 @@
  */
 package org.apache.fontbox.cff;
 
-import java.io.EOFException;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /**
  * This class contains some functionality to read a byte buffer.
@@ -34,8 +29,6 @@ public class DataInput
     private byte[] inputBuffer = null;
     private int bufferPosition = 0;
 
-    private static final Log LOG = LogFactory.getLog(DataInput.class);
-
     /**
      * Constructor.
      * @param buffer the buffer to be read
@@ -65,23 +58,24 @@ public class DataInput
 
     /**
      * Sets the current position to the given value.
+     * 
      * @param position the given position
+     * @throws IOException if the new position ist out of range
      */
-    public void setPosition(int position)
+    public void setPosition(int position) throws IOException
     {
+        if (position < 0)
+        {
+            throw new IOException("position is negative");
+        }
+        if (position >= inputBuffer.length)
+        {
+            throw new IOException(
+                    "New position is out of range " + position + " >= " + inputBuffer.length);
+        }
         bufferPosition = position;
     }
 
-    /** 
-     * Returns the buffer as an ISO-8859-1 string.
-     * @return the buffer as string
-     * @throws IOException if an error occurs during reading
-     */
-    public String getString() throws IOException
-    {
-        return new String(inputBuffer, StandardCharsets.ISO_8859_1);
-    }
-
     /**
      * Read one single byte from the buffer.
      * @return the byte
@@ -89,17 +83,11 @@ public class DataInput
      */
     public byte readByte() throws IOException
     {
-        try
-        {
-            byte value = inputBuffer[bufferPosition];
-            bufferPosition++;
-            return value;
-        } 
-        catch (RuntimeException re)
+        if (!hasRemaining())
         {
-            LOG.debug("An error occurred reading a byte - returning -1", re);
-            return -1;
+            throw new IOException("End off buffer reached");
         }
+        return inputBuffer[bufferPosition++];
     }
 
     /**
@@ -109,27 +97,32 @@ public class DataInput
      */
     public int readUnsignedByte() throws IOException
     {
-        int b = read();
-        if (b < 0)
+        if (!hasRemaining())
         {
-            throw new EOFException();
+            throw new IOException("End off buffer reached");
         }
-        return b;
+        return inputBuffer[bufferPosition++] & 0xff;
     }
 
     /**
      * Peeks one single unsigned byte from the buffer.
+     * 
+     * @param offset offset to the byte to be peeked
      * @return the unsigned byte as int
      * @throws IOException if an error occurs during reading
      */
     public int peekUnsignedByte(int offset) throws IOException
     {
-        int b = peek(offset);
-        if (b < 0)
+        if (offset < 0)
         {
-            throw new EOFException();
+            throw new IOException("offset is negative");
         }
-        return b;
+        if (bufferPosition + offset >= inputBuffer.length)
+        {
+            throw new IOException("Offset position is out of range " + (bufferPosition + offset)
+                    + " >= " + inputBuffer.length);
+        }
+        return inputBuffer[bufferPosition + offset] & 0xff;
     }
 
     /**
@@ -149,12 +142,8 @@ public class DataInput
      */
     public int readUnsignedShort() throws IOException
     {
-        int b1 = read();
-        int b2 = read();
-        if ((b1 | b2) < 0)
-        {
-            throw new EOFException();
-        }
+        int b1 = readUnsignedByte();
+        int b2 = readUnsignedByte();
         return b1 << 8 | b2;
     }
 
@@ -165,14 +154,10 @@ public class DataInput
      */
     public int readInt() throws IOException
     {
-        int b1 = read();
-        int b2 = read();
-        int b3 = read();
-        int b4 = read();
-        if ((b1 | b2 | b3 | b4) < 0)
-        {
-            throw new EOFException();
-        }
+        int b1 = readUnsignedByte();
+        int b2 = readUnsignedByte();
+        int b3 = readUnsignedByte();
+        int b4 = readUnsignedByte();
         return b1 << 24 | b2 << 16 | b3 << 8 | b4;
     }
 
@@ -190,7 +175,7 @@ public class DataInput
         }
         if (inputBuffer.length - bufferPosition < length)
         {
-            throw new EOFException(); 
+            throw new IOException("Premature end of buffer reached");
         }
         byte[] bytes = new byte[length];
         System.arraycopy(inputBuffer, bufferPosition, bytes, 0, length);
@@ -198,34 +183,6 @@ public class DataInput
         return bytes;
     }
 
-    private int read()
-    {
-        try
-        {
-            int value = inputBuffer[bufferPosition] & 0xff;
-            bufferPosition++;
-            return value;
-        } 
-        catch (RuntimeException re)
-        {
-            LOG.debug("An error occurred reading an int - returning -1", re);
-            return -1;
-        }
-    }
-
-    private int peek(int offset)
-    {
-        try
-        {
-            return inputBuffer[bufferPosition + offset] & 0xff;
-        }
-        catch (RuntimeException re)
-        {
-            LOG.debug("An error occurred peeking at offset " + offset + " - returning -1", re);
-            return -1;
-        }
-    }
-    
     public int length()
     {
         return inputBuffer.length;

Added: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java?rev=1888997&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java (added)
+++ pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java Tue Apr 20 06:26:38 2021
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fontbox.cff;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+class DataInputTest
+{
+    @Test
+    void testReadBytes() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInput(data);
+        assertThrows(IOException.class, () -> dataInput.readBytes(20));
+        assertArrayEquals(new byte[] { 0 }, dataInput.readBytes(1));
+        assertArrayEquals(new byte[] { -1, 2, -3 }, dataInput.readBytes(3));
+        dataInput.setPosition(6);
+        assertArrayEquals(new byte[] { 6, -7, 8 }, dataInput.readBytes(3));
+        assertThrows(IOException.class, () -> dataInput.readBytes(-1));
+        assertThrows(IOException.class, () -> dataInput.readBytes(5));
+    }
+
+    @Test
+    void testReadByte() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(0, dataInput.readByte());
+        assertEquals(-1, dataInput.readByte());
+        dataInput.setPosition(6);
+        assertEquals(6, dataInput.readByte());
+        assertEquals(-7, dataInput.readByte());
+        dataInput.setPosition(dataInput.length() - 1);
+        assertEquals(-9, dataInput.readByte());
+        assertThrows(IOException.class, () -> dataInput.readByte());
+    }
+
+    @Test
+    void testReadUnsignedByte() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(0, dataInput.readUnsignedByte());
+        assertEquals(255, dataInput.readUnsignedByte());
+        dataInput.setPosition(6);
+        assertEquals(6, dataInput.readUnsignedByte());
+        assertEquals(249, dataInput.readUnsignedByte());
+        dataInput.setPosition(dataInput.length() - 1);
+        assertEquals(247, dataInput.readUnsignedByte());
+        assertThrows(IOException.class, () -> dataInput.readUnsignedByte());
+    }
+
+    @Test
+    void testBasics() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(10, dataInput.length());
+        assertTrue(dataInput.hasRemaining());
+        assertThrows(IOException.class, () -> dataInput.setPosition(-1));
+        assertThrows(IOException.class, () -> dataInput.setPosition(dataInput.length()));
+    }
+
+    @Test
+    void testPeek() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(0, dataInput.peekUnsignedByte(0));
+        assertEquals(251, dataInput.peekUnsignedByte(5));
+        assertThrows(IOException.class, () -> dataInput.peekUnsignedByte(-1));
+        assertThrows(IOException.class, () -> dataInput.peekUnsignedByte(dataInput.length()));
+    }
+
+    @Test
+    void testReadShort() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
+        DataInput dataInput = new DataInput(data);
+        assertEquals((short) 0x000F, dataInput.readShort());
+        assertEquals((short) 0xAA00, dataInput.readShort());
+        assertEquals((short) 0xFEFF, dataInput.readShort());
+        assertThrows(IOException.class, () -> dataInput.readShort());
+    }
+
+    @Test
+    void testReadUnsignedShort() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(0x000F, dataInput.readUnsignedShort());
+        assertEquals(0xAA00, dataInput.readUnsignedShort());
+        assertEquals(0xFEFF, dataInput.readUnsignedShort());
+        assertThrows(IOException.class, () -> dataInput.readUnsignedShort());
+
+        byte[] data2 = new byte[] { 0x00 };
+        DataInput dataInput2 = new DataInput(data2);
+        assertThrows(IOException.class, () -> dataInput2.readUnsignedShort());
+    }
+
+    @Test
+    void testReadInt() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF, 0x30,
+                0x50 };
+        DataInput dataInput = new DataInput(data);
+        assertEquals(0x000FAA00, dataInput.readInt());
+        assertEquals(0xFEFF3050, dataInput.readInt());
+        assertThrows(IOException.class, () -> dataInput.readInt());
+
+        byte[] data2 = new byte[] { 0x00, 0x0F, (byte) 0xAA };
+        DataInput dataInput2 = new DataInput(data2);
+        assertThrows(IOException.class, () -> dataInput2.readInt());
+
+    }
+}

Propchange: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java
------------------------------------------------------------------------------
    svn:eol-style = native