Skip to content

Commit

Permalink
Fix integer addition overflow.
Browse files Browse the repository at this point in the history
    An integer overflow can occur when extending the index, preventing guard statements from catching indices outside the expected buffer range and resulting in OutOfMemory exceptions from array allocation.
  • Loading branch information
cniles committed Mar 31, 2022
1 parent e9733f0 commit ecff9b4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
10 changes: 5 additions & 5 deletions Source/com/drew/lang/SequentialByteArrayReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public byte getByte() throws IOException
@Override
public byte[] getBytes(int count) throws IOException
{
if (_index + count > _bytes.length) {
if ((long)_index + count > _bytes.length) {
throw new EOFException("End of data reached.");
}

Expand All @@ -84,7 +84,7 @@ public byte[] getBytes(int count) throws IOException
@Override
public void getBytes(@NotNull byte[] buffer, int offset, int count) throws IOException
{
if (_index + count > _bytes.length) {
if ((long)_index + count > _bytes.length) {
throw new EOFException("End of data reached.");
}

Expand Down Expand Up @@ -113,13 +113,13 @@ public boolean trySkip(long n) throws IOException
throw new IllegalArgumentException("n must be zero or greater.");
}

_index += n;

if (_index > _bytes.length) {
if (_index + n > _bytes.length) {
_index = _bytes.length;
return false;
}

_index += n;

return true;
}

Expand Down
11 changes: 8 additions & 3 deletions Source/com/drew/lang/StreamReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,14 @@ public byte getByte() throws IOException
@Override
public byte[] getBytes(int count) throws IOException
{
byte[] bytes = new byte[count];
getBytes(bytes, 0, count);
return bytes;
try {
byte[] bytes = new byte[count];
getBytes(bytes, 0, count);
return bytes;
} catch (OutOfMemoryError e) {
throw new EOFException("End of data reached.");
}

}

@Override
Expand Down
24 changes: 21 additions & 3 deletions Tests/com/drew/lang/SequentialAccessTestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public abstract class SequentialAccessTestBase
@Test
public void testDefaultEndianness()
{
assertEquals(true, createReader(new byte[1]).isMotorolaByteOrder());
assertTrue(createReader(new byte[1]).isMotorolaByteOrder());
}

@Test
Expand Down Expand Up @@ -269,13 +269,20 @@ public void testGetBytes() throws IOException
@Test
public void testOverflowBoundsCalculation()
{
SequentialReader reader = createReader(new byte[10]);

try {
SequentialReader reader = createReader(new byte[10]);
reader.getBytes(15);
} catch (IOException e) {
assertEquals("End of data reached.", e.getMessage());
}

try {
SequentialReader reader = createReader(new byte[10]);
reader.getBytes(5);
reader.getBytes(Integer.MAX_VALUE);
} catch (IOException e) {
assertEquals("End of data reached.", e.getMessage());
}
}

@Test
Expand Down Expand Up @@ -325,6 +332,13 @@ public void testSkipEOF() throws Exception
reader.skip(1);
fail("Expecting exception");
} catch (EOFException ignored) {}

try {
reader = createReader(new byte[100]);
reader.skip(50);
reader.skip(Integer.MAX_VALUE);
fail("Expecting exception");
} catch (EOFException ignored) {}
}

@Test
Expand All @@ -336,5 +350,9 @@ public void testTrySkipEOF() throws Exception
assertTrue(reader.trySkip(1));
assertTrue(reader.trySkip(1));
assertFalse(reader.trySkip(1));

reader = createReader(new byte[100]);
reader.getBytes(50);
assertFalse(reader.trySkip(Integer.MAX_VALUE));
}
}

0 comments on commit ecff9b4

Please sign in to comment.