mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Allow a maximum length to be specified when reading strings or byte
arrays, check it before allocating the buffer, and always specify the maximum length when reading untrusted data - otherwise CountingConsumer will reject the packet, but not before we've tried to allocate a buffer of the specified size (up to 2 GB).
This commit is contained in:
@@ -31,8 +31,8 @@ class AuthorReader implements ObjectReader<Author> {
|
||||
// Read and digest the data
|
||||
r.addConsumer(digesting);
|
||||
r.readUserDefinedTag(Tags.AUTHOR);
|
||||
String name = r.readString();
|
||||
byte[] publicKey = r.readBytes();
|
||||
String name = r.readString(Author.MAX_NAME_LENGTH);
|
||||
byte[] publicKey = r.readBytes(Author.MAX_PUBLIC_KEY_LENGTH);
|
||||
r.removeConsumer(digesting);
|
||||
// Build and return the author
|
||||
AuthorId id = new AuthorId(messageDigest.digest());
|
||||
|
||||
@@ -13,7 +13,7 @@ class BatchIdReader implements ObjectReader<BatchId> {
|
||||
|
||||
public BatchId readObject(Reader r) throws IOException {
|
||||
r.readUserDefinedTag(Tags.BATCH_ID);
|
||||
byte[] b = r.readBytes();
|
||||
byte[] b = r.readBytes(UniqueId.LENGTH);
|
||||
if(b.length != UniqueId.LENGTH) throw new FormatException();
|
||||
return new BatchId(b);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class GroupIdReader implements ObjectReader<GroupId> {
|
||||
|
||||
public GroupId readObject(Reader r) throws IOException {
|
||||
r.readUserDefinedTag(Tags.GROUP_ID);
|
||||
byte[] b = r.readBytes();
|
||||
byte[] b = r.readBytes(UniqueId.LENGTH);
|
||||
if(b.length != UniqueId.LENGTH) throw new FormatException();
|
||||
return new GroupId(b);
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ class GroupReader implements ObjectReader<Group> {
|
||||
// Read and digest the data
|
||||
r.addConsumer(digesting);
|
||||
r.readUserDefinedTag(Tags.GROUP);
|
||||
String name = r.readString();
|
||||
String name = r.readString(Group.MAX_NAME_LENGTH);
|
||||
byte[] publicKey = null;
|
||||
if(r.hasNull()) r.readNull();
|
||||
else publicKey = r.readBytes();
|
||||
else publicKey = r.readBytes(Group.MAX_PUBLIC_KEY_LENGTH);
|
||||
r.removeConsumer(digesting);
|
||||
// Build and return the group
|
||||
GroupId id = new GroupId(messageDigest.digest());
|
||||
|
||||
@@ -13,7 +13,7 @@ class MessageIdReader implements ObjectReader<MessageId> {
|
||||
|
||||
public MessageId readObject(Reader r) throws IOException {
|
||||
r.readUserDefinedTag(Tags.MESSAGE_ID);
|
||||
byte[] b = r.readBytes();
|
||||
byte[] b = r.readBytes(UniqueId.LENGTH);
|
||||
if(b.length != UniqueId.LENGTH) throw new FormatException();
|
||||
return new MessageId(b);
|
||||
}
|
||||
|
||||
@@ -67,19 +67,19 @@ class MessageReader implements ObjectReader<Message> {
|
||||
long timestamp = r.readInt64();
|
||||
if(timestamp < 0L) throw new FormatException();
|
||||
// Skip the message body
|
||||
r.readBytes();
|
||||
r.readBytes(Message.MAX_SIZE);
|
||||
// Record the length of the data covered by the author's signature
|
||||
int signedByAuthor = (int) counting.getCount();
|
||||
// Read the author's signature, if there is one
|
||||
byte[] authorSig = null;
|
||||
if(author == null) r.readNull();
|
||||
else authorSig = r.readBytes();
|
||||
else authorSig = r.readBytes(Message.MAX_SIGNATURE_SIZE);
|
||||
// Record the length of the data covered by the group's signature
|
||||
int signedByGroup = (int) counting.getCount();
|
||||
// Read the group's signature, if there is one
|
||||
byte[] groupSig = null;
|
||||
if(group.getPublicKey() == null) r.readNull();
|
||||
else groupSig = r.readBytes();
|
||||
else groupSig = r.readBytes(Message.MAX_SIGNATURE_SIZE);
|
||||
// That's all, folks
|
||||
r.removeConsumer(counting);
|
||||
r.removeConsumer(copying);
|
||||
|
||||
@@ -26,7 +26,7 @@ class RequestReader implements ObjectReader<Request> {
|
||||
// Read the data
|
||||
r.addConsumer(counting);
|
||||
r.readUserDefinedTag(Tags.REQUEST);
|
||||
byte[] bitmap = r.readBytes();
|
||||
byte[] bitmap = r.readBytes(Request.MAX_SIZE);
|
||||
r.removeConsumer(counting);
|
||||
// Convert the bitmap into a BitSet
|
||||
BitSet b = new BitSet(bitmap.length * 8);
|
||||
|
||||
@@ -268,18 +268,16 @@ class ReaderImpl implements Reader {
|
||||
}
|
||||
|
||||
public String readString() throws IOException {
|
||||
if(!hasString()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
if(next == Tag.STRING) {
|
||||
return readString(readLength());
|
||||
} else {
|
||||
int length = 0xFF & next ^ Tag.SHORT_STRING;
|
||||
return readString(length);
|
||||
}
|
||||
return readString(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
private String readString(int length) throws IOException {
|
||||
assert length >= 0;
|
||||
public String readString(int maxLength) throws IOException {
|
||||
if(!hasString()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
int length;
|
||||
if(next == Tag.STRING) length = readLength();
|
||||
else length = 0xFF & next ^ Tag.SHORT_STRING;
|
||||
if(length > maxLength) throw new FormatException();
|
||||
if(length == 0) return "";
|
||||
readIntoBuffer(length);
|
||||
return new String(buf, 0, length, "UTF-8");
|
||||
@@ -308,18 +306,16 @@ class ReaderImpl implements Reader {
|
||||
}
|
||||
|
||||
public byte[] readBytes() throws IOException {
|
||||
if(!hasBytes()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
if(next == Tag.BYTES) {
|
||||
return readBytes(readLength());
|
||||
} else {
|
||||
int length = 0xFF & next ^ Tag.SHORT_BYTES;
|
||||
return readBytes(length);
|
||||
}
|
||||
return readBytes(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
private byte[] readBytes(int length) throws IOException {
|
||||
assert length >= 0;
|
||||
public byte[] readBytes(int maxLength) throws IOException {
|
||||
if(!hasBytes()) throw new FormatException();
|
||||
consumeLookahead();
|
||||
int length;
|
||||
if(next == Tag.BYTES) length = readLength();
|
||||
else length = 0xFF & next ^ Tag.SHORT_BYTES;
|
||||
if(length > maxLength) throw new FormatException();
|
||||
if(length == 0) return EMPTY_BUFFER;
|
||||
byte[] b = new byte[length];
|
||||
readIntoBuffer(b, length);
|
||||
|
||||
Reference in New Issue
Block a user