Author: tilman
Date: Fri Apr 25 14:19:40 2025
New Revision: 1925264

URL: http://svn.apache.org/viewvc?rev=1925264&view=rev
Log:
PDFBOX-5965: combine LAST and CURRENT buffers into new LAST buffer content to 
avoid ArrayIndexOutOfBoundsException

Modified:
    
pdfbox/branches/3.0/io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java
    
pdfbox/branches/3.0/io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java

Modified: 
pdfbox/branches/3.0/io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/3.0/io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java?rev=1925264&r1=1925263&r2=1925264&view=diff
==============================================================================
--- 
pdfbox/branches/3.0/io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java
 (original)
+++ 
pdfbox/branches/3.0/io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java
 Fri Apr 25 14:19:40 2025
@@ -190,7 +190,21 @@ public class NonSeekableRandomAccessRead
         {
             // move the current data to last to support rewind operations
             // right after refilling the current buffer
-            switchBuffers(CURRENT, LAST);
+            if (bufferBytes[LAST] == BUFFER_SIZE && bufferBytes[CURRENT] > 0 
&& bufferBytes[CURRENT] < BUFFER_SIZE)
+            {
+                // Likely EOF, we're risking losing the previous (full) buffer 
and get an AIOOB
+                // Create a new LAST buffer that combines as much as possible 
of CURRENT and LAST into a new LAST.
+                byte[] newBuffer = new byte[BUFFER_SIZE];
+                System.arraycopy(buffers[LAST], bufferBytes[CURRENT], 
newBuffer, 0, BUFFER_SIZE - bufferBytes[CURRENT]);
+                System.arraycopy(buffers[CURRENT], 0, newBuffer, BUFFER_SIZE - 
bufferBytes[CURRENT], bufferBytes[CURRENT]);
+                switchBuffers(CURRENT, LAST);
+                buffers[LAST] = newBuffer;
+                bufferBytes[LAST] = BUFFER_SIZE;
+            }
+            else
+            {
+                switchBuffers(CURRENT, LAST);
+            }
             bufferBytes[CURRENT] = is.read(buffers[CURRENT]);
             if (bufferBytes[CURRENT] <= 0)
             {

Modified: 
pdfbox/branches/3.0/io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/3.0/io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java?rev=1925264&r1=1925263&r2=1925264&view=diff
==============================================================================
--- 
pdfbox/branches/3.0/io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java
 (original)
+++ 
pdfbox/branches/3.0/io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java
 Fri Apr 25 14:19:40 2025
@@ -221,6 +221,29 @@ class NonSeekableRandomAccessReadInputSt
         }
     }
 
+    @Test
+    void testRewindAcrossBuffers() throws IOException
+    {
+        byte[] ba = new byte[4096 + 5];
+        int rewSize = 7;
+        byte testVal = 123;
+        ba[ba.length - rewSize] = testVal;
+        ByteArrayInputStream bais = new ByteArrayInputStream(ba);
+        try (RandomAccessRead rar = new 
NonSeekableRandomAccessReadInputStream(bais))
+        {
+            int len = rar.read(new byte[ba.length - rewSize]);
+            assertEquals(ba.length - rewSize, len);
+            len = rar.read(new byte[rewSize]);
+            assertEquals(rewSize, len);
+            int by = rar.read();
+            assertEquals(-1, by);
+            assertTrue(rar.isEOF());
+            rar.rewind(len);
+            by = rar.read(); // went ArrayIndexOutOfBoundsException here
+            assertEquals(testVal, by);
+        }
+    }
+
     private byte[] createRandomData()
     {
         final long seed = new Random().nextLong();


Reply via email to