Skip to content

Commit

Permalink
MINOR: after reading BYTES type it's possible to access data beyond i…
Browse files Browse the repository at this point in the history
…ts size (apache#13261)

After reading data of type BYTES, COMPACT_BYTES, NULLABLE_BYTES or COMPACT_NULLABLE_BYTES returned ByteBuffer might have a capacity that is larger than its limit, thus these data types may access data that lies beyond its size by increasing limit of the returned ByteBuffer. I guess this is not very critical but I think it would be good to restrict increasing limit of the returned ByteBuffer by making its capacity strictly equal to its limit. I think someone might unintentionally mishandle these data types and accidentally mess up data in the ByteBuffer from which they were read.

Reviewers: Luke Chen <showuon@gmail.com>
  • Loading branch information
bachmanity1 committed Feb 23, 2023
1 parent db6beb9 commit 3fe2f8c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -689,9 +689,12 @@ public Object read(ByteBuffer buffer) {
if (size > buffer.remaining())
throw new SchemaException("Error reading bytes of size " + size + ", only " + buffer.remaining() + " bytes available");

int limit = buffer.limit();
int newPosition = buffer.position() + size;
buffer.limit(newPosition);
ByteBuffer val = buffer.slice();
val.limit(size);
buffer.position(buffer.position() + size);
buffer.limit(limit);
buffer.position(newPosition);
return val;
}

Expand Down Expand Up @@ -739,9 +742,12 @@ public Object read(ByteBuffer buffer) {
if (size > buffer.remaining())
throw new SchemaException("Error reading bytes of size " + size + ", only " + buffer.remaining() + " bytes available");

int limit = buffer.limit();
int newPosition = buffer.position() + size;
buffer.limit(newPosition);
ByteBuffer val = buffer.slice();
val.limit(size);
buffer.position(buffer.position() + size);
buffer.limit(limit);
buffer.position(newPosition);
return val;
}

Expand Down Expand Up @@ -800,9 +806,12 @@ public Object read(ByteBuffer buffer) {
if (size > buffer.remaining())
throw new SchemaException("Error reading bytes of size " + size + ", only " + buffer.remaining() + " bytes available");

int limit = buffer.limit();
int newPosition = buffer.position() + size;
buffer.limit(newPosition);
ByteBuffer val = buffer.slice();
val.limit(size);
buffer.position(buffer.position() + size);
buffer.limit(limit);
buffer.position(newPosition);
return val;
}

Expand Down Expand Up @@ -865,9 +874,12 @@ public Object read(ByteBuffer buffer) {
if (size > buffer.remaining())
throw new SchemaException("Error reading bytes of size " + size + ", only " + buffer.remaining() + " bytes available");

int limit = buffer.limit();
int newPosition = buffer.position() + size;
buffer.limit(newPosition);
ByteBuffer val = buffer.slice();
val.limit(size);
buffer.position(buffer.position() + size);
buffer.limit(limit);
buffer.position(newPosition);
return val;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,21 @@ public void testReadWithMissingNonOptionalExtraDataAtTheEnd() {
SchemaException e = assertThrows(SchemaException.class, () -> newSchema.read(buffer));
assertTrue(e.getMessage().contains("Missing value for field 'field2' which has no default value"));
}

@Test
public void testReadBytesBeyondItsSize() {
Type[] types = new Type[]{
Type.BYTES,
Type.COMPACT_BYTES,
Type.NULLABLE_BYTES,
Type.COMPACT_NULLABLE_BYTES
};
for (Type type : types) {
ByteBuffer buffer = ByteBuffer.allocate(20);
type.write(buffer, ByteBuffer.allocate(4));
buffer.rewind();
ByteBuffer bytes = (ByteBuffer) type.read(buffer);
assertThrows(IllegalArgumentException.class, () -> bytes.limit(bytes.limit() + 1));
}
}
}

0 comments on commit 3fe2f8c

Please sign in to comment.