Skip to content

Commit d9c1b7a

Browse files
committed
PDFBOX-5965: combine LAST and CURRENT buffers into new LAST buffer content to avoid ArrayIndexOutOfBoundsException
git-svn-id: https://svn.apache.org/repos/asf/pdfbox/trunk@1925263 13f79535-47bb-0310-9956-ffa450edef68
1 parent 84230f1 commit d9c1b7a

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

io/src/main/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStream.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,21 @@ private boolean fetch() throws IOException
192192
{
193193
// move the current data to last to support rewind operations
194194
// right after refilling the current buffer
195-
switchBuffers(CURRENT, LAST);
195+
if (bufferBytes[LAST] == BUFFER_SIZE && bufferBytes[CURRENT] > 0 && bufferBytes[CURRENT] < BUFFER_SIZE)
196+
{
197+
// Likely EOF, we're risking losing the previous (full) buffer and get an AIOOB
198+
// Create a new LAST buffer that combines as much as possible of CURRENT and LAST into a new LAST.
199+
byte[] newBuffer = new byte[BUFFER_SIZE];
200+
System.arraycopy(buffers[LAST], bufferBytes[CURRENT], newBuffer, 0, BUFFER_SIZE - bufferBytes[CURRENT]);
201+
System.arraycopy(buffers[CURRENT], 0, newBuffer, BUFFER_SIZE - bufferBytes[CURRENT], bufferBytes[CURRENT]);
202+
switchBuffers(CURRENT, LAST);
203+
buffers[LAST] = newBuffer;
204+
bufferBytes[LAST] = BUFFER_SIZE;
205+
}
206+
else
207+
{
208+
switchBuffers(CURRENT, LAST);
209+
}
196210
bufferBytes[CURRENT] = is.read(buffers[CURRENT]);
197211
if (bufferBytes[CURRENT] <= 0)
198212
{

io/src/test/java/org/apache/pdfbox/io/NonSeekableRandomAccessReadInputStreamTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,29 @@ void testRewindException() throws IOException
221221
}
222222
}
223223

224+
@Test
225+
void testRewindAcrossBuffers() throws IOException
226+
{
227+
byte[] ba = new byte[4096 + 5];
228+
int rewSize = 7;
229+
byte testVal = 123;
230+
ba[ba.length - rewSize] = testVal;
231+
ByteArrayInputStream bais = new ByteArrayInputStream(ba);
232+
try (RandomAccessRead rar = new NonSeekableRandomAccessReadInputStream(bais))
233+
{
234+
int len = rar.read(new byte[ba.length - rewSize]);
235+
assertEquals(ba.length - rewSize, len);
236+
len = rar.read(new byte[rewSize]);
237+
assertEquals(rewSize, len);
238+
int by = rar.read();
239+
assertEquals(-1, by);
240+
assertTrue(rar.isEOF());
241+
rar.rewind(len);
242+
by = rar.read(); // went ArrayIndexOutOfBoundsException here
243+
assertEquals(testVal, by);
244+
}
245+
}
246+
224247
private byte[] createRandomData()
225248
{
226249
final long seed = new Random().nextLong();

0 commit comments

Comments
 (0)