From 5a0953067043cc411c60b39c80ccc6d0b4673c0f Mon Sep 17 00:00:00 2001 From: akwizgran Date: Sat, 18 Feb 2023 17:10:57 +0000 Subject: [PATCH 1/9] Reject invalid UTF-8 instead of ignoring it. --- .../bramble/util/StringUtils.java | 27 ++++++++---- .../data/BdfReaderImplFuzzingTest.java | 12 ++++-- .../bramble/util/StringUtilsTest.java | 41 +++++++++++-------- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java index d9a19e70a..59beeeee2 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java @@ -14,6 +14,7 @@ import java.util.regex.Pattern; import javax.annotation.Nullable; import static java.nio.charset.CodingErrorAction.IGNORE; +import static java.nio.charset.CodingErrorAction.REPORT; import static java.util.regex.Pattern.CASE_INSENSITIVE; @SuppressWarnings("CharsetObjectCanBeUsed") @@ -52,26 +53,38 @@ public class StringUtils { return s.getBytes(UTF_8); } - public static String fromUtf8(byte[] bytes) { - return fromUtf8(bytes, 0, bytes.length); + public static String fromUtf8(byte[] bytes) throws FormatException { + return fromUtf8(bytes, 0, bytes.length, true); } - public static String fromUtf8(byte[] bytes, int off, int len) { + public static String fromUtf8(byte[] bytes, int off, int len) + throws FormatException { + return fromUtf8(bytes, off, len, true); + } + + private static String fromUtf8(byte[] bytes, int off, int len, + boolean strict) throws FormatException { CharsetDecoder decoder = UTF_8.newDecoder(); - decoder.onMalformedInput(IGNORE); - decoder.onUnmappableCharacter(IGNORE); + decoder.onMalformedInput(strict ? REPORT : IGNORE); + decoder.onUnmappableCharacter(strict ? REPORT : IGNORE); ByteBuffer buffer = ByteBuffer.wrap(bytes, off, len); try { return decoder.decode(buffer).toString(); } catch (CharacterCodingException e) { - throw new AssertionError(e); + throw new FormatException(); } } public static String truncateUtf8(String s, int maxUtf8Length) { byte[] utf8 = toUtf8(s); if (utf8.length <= maxUtf8Length) return s; - return fromUtf8(utf8, 0, maxUtf8Length); + // Don't be strict when converting back, so that if we truncate a + // multi-byte character the whole character gets dropped + try { + return fromUtf8(utf8, 0, maxUtf8Length, false); + } catch (FormatException e) { + throw new AssertionError(e); + } } /** diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java index 852e66853..f83a6bc6f 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.data; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Before; import org.junit.Test; @@ -32,10 +33,13 @@ public class BdfReaderImplFuzzingTest extends BrambleTestCase { in.reset(); BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, DEFAULT_MAX_BUFFER_SIZE); - int length = r.readString().length(); - assertTrue(length >= 0); - assertTrue(length <= 20); - assertTrue(r.eof()); + try { + int length = r.readString().length(); + assertTrue(length <= 20); + assertTrue(r.eof()); + } catch (FormatException e) { + // Expected when bytes are not valid UTF-8 + } } } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java b/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java index 593640824..b3c13c27b 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java @@ -88,51 +88,58 @@ public class StringUtilsTest extends BrambleTestCase { } @Test - public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8() { + public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8() + throws Exception { // The UTF-8 encoding of the null character is valid - assertEquals("\u0000", StringUtils.fromUtf8(new byte[1])); + byte[] utf8 = new byte[1]; + String actual = StringUtils.fromUtf8(utf8); + assertEquals("\u0000", actual); + // When we convert back to UTF-8 we should get the original encoding + assertArrayEquals(utf8, StringUtils.toUtf8(actual)); } - @Test - public void testFromUtf8RemovesNullCharacterUsingModifiedUtf8() { + @Test(expected = FormatException.class) + public void testFromUtf8RejectsNullCharacterUsingModifiedUtf8() + throws Exception { // The modified UTF-8 encoding of the null character is not valid byte[] b = new byte[] { (byte) 0xC0, (byte) 0x80, // Null character as modified UTF-8 (byte) 0xC8, (byte) 0x85 // U+0205 }; - // Conversion should ignore the invalid character and return the rest - String expected = "\u0205"; - assertEquals(expected, StringUtils.fromUtf8(b)); + StringUtils.fromUtf8(b); } @Test - public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8() { + public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8() + throws Exception { // The UTF-8 encoding of a supplementary character is valid and should // be converted to a surrogate pair - byte[] b = new byte[] { + byte[] utf8 = new byte[] { (byte) 0xF0, (byte) 0x90, (byte) 0x90, (byte) 0x80, // U+10400 (byte) 0xC8, (byte) 0x85 // U+0205 }; String expected = "\uD801\uDC00\u0205"; // Surrogate pair - assertEquals(expected, StringUtils.fromUtf8(b)); + String actual = StringUtils.fromUtf8(utf8); + assertEquals(expected, actual); + // When we convert back to UTF-8 we should get the original encoding + assertArrayEquals(utf8, StringUtils.toUtf8(actual)); } - @Test - public void testFromUtf8RemovesSupplementaryCharacterUsingModifiedUtf8() { + @Test(expected = FormatException.class) + public void testFromUtf8RejectsSupplementaryCharacterUsingModifiedUtf8() + throws Exception { // The CESU-8 or modified UTF-8 encoding of a supplementary character // is not valid - byte[] b = new byte[] { + byte[] utf8 = new byte[] { (byte) 0xED, (byte) 0xA0, (byte) 0x81, // U+10400 as CSEU-8 (byte) 0xED, (byte) 0xB0, (byte) 0x80, (byte) 0xC8, (byte) 0x85 // U+0205 }; - // Conversion should ignore the invalid character and return the rest - String expected = "\u0205"; - assertEquals(expected, StringUtils.fromUtf8(b)); + StringUtils.fromUtf8(utf8); } @Test - public void testFromUtf8EmptyInput() { + public void testFromUtf8EmptyInput() throws Exception { assertEquals("", StringUtils.fromUtf8(new byte[0])); } From ac8a4db457094e85ee1f73eb12c5c5c30bea3980 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 17 Feb 2023 22:51:49 +0000 Subject: [PATCH 2/9] Add support for reading and writing BDF in canonical form. Existing transport property updates may not be in canonical form, so we need to parse them leniently. --- .../api/client/BdfMessageValidator.java | 14 +- .../bramble/api/client/ClientHelper.java | 5 + .../bramble/api/data/BdfReaderFactory.java | 4 +- .../bramble/client/ClientHelperImpl.java | 23 ++- .../bramble/data/BdfReaderFactoryImpl.java | 12 +- .../bramble/data/BdfReaderImpl.java | 33 +++- .../bramble/data/BdfWriterImpl.java | 24 ++- .../TransportPropertyManagerImpl.java | 12 +- .../TransportPropertyValidator.java | 5 +- .../client/BdfMessageValidatorTest.java | 8 +- .../bramble/client/ClientHelperImplTest.java | 2 +- .../data/BdfReaderImplFuzzingTest.java | 2 +- .../bramble/data/BdfReaderImplTest.java | 147 +++++++++++++----- .../data/BdfReaderWriterIntegrationTest.java | 80 ++++++++++ .../TransportPropertyManagerImplTest.java | 18 ++- 15 files changed, 309 insertions(+), 80 deletions(-) create mode 100644 bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderWriterIntegrationTest.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java index 4caed6438..468c64126 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/BdfMessageValidator.java @@ -16,6 +16,7 @@ import java.util.logging.Logger; import javax.annotation.concurrent.Immutable; +import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE; @Immutable @@ -23,17 +24,24 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC public abstract class BdfMessageValidator implements MessageValidator { protected static final Logger LOG = - Logger.getLogger(BdfMessageValidator.class.getName()); + getLogger(BdfMessageValidator.class.getName()); protected final ClientHelper clientHelper; protected final MetadataEncoder metadataEncoder; protected final Clock clock; + protected final boolean canonical; protected BdfMessageValidator(ClientHelper clientHelper, - MetadataEncoder metadataEncoder, Clock clock) { + MetadataEncoder metadataEncoder, Clock clock, boolean canonical) { this.clientHelper = clientHelper; this.metadataEncoder = metadataEncoder; this.clock = clock; + this.canonical = canonical; + } + + protected BdfMessageValidator(ClientHelper clientHelper, + MetadataEncoder metadataEncoder, Clock clock) { + this(clientHelper, metadataEncoder, clock, true); } protected abstract BdfMessageContext validateMessage(Message m, Group g, @@ -49,7 +57,7 @@ public abstract class BdfMessageValidator implements MessageValidator { "Timestamp is too far in the future"); } try { - BdfList bodyList = clientHelper.toList(m.getBody()); + BdfList bodyList = clientHelper.toList(m, canonical); BdfMessageContext result = validateMessage(m, g, bodyList); Metadata meta = metadataEncoder.encode(result.getDictionary()); return new MessageContext(meta, result.getDependencies()); diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java index 9ccd18f1d..ff8ee773c 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java @@ -49,6 +49,9 @@ public interface ClientHelper { BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException, FormatException; + BdfList getMessageAsList(Transaction txn, MessageId m, boolean canonical) + throws DbException, FormatException; + BdfDictionary getGroupMetadataAsDictionary(GroupId g) throws DbException, FormatException; @@ -106,6 +109,8 @@ public interface ClientHelper { BdfList toList(Message m) throws FormatException; + BdfList toList(Message m, boolean canonical) throws FormatException; + BdfList toList(Author a); byte[] sign(String label, BdfList toSign, PrivateKey privateKey) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java index bc41a66d3..5ff95dfa1 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReaderFactory.java @@ -9,6 +9,8 @@ public interface BdfReaderFactory { BdfReader createReader(InputStream in); + BdfReader createReader(InputStream in, boolean canonical); + BdfReader createReader(InputStream in, int nestedLimit, - int maxBufferSize); + int maxBufferSize, boolean canonical); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java index 1e1939cd8..30d7d641b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java @@ -155,7 +155,13 @@ class ClientHelperImpl implements ClientHelper { @Override public BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException, FormatException { - return toList(db.getMessage(txn, m).getBody()); + return getMessageAsList(txn, m, true); + } + + @Override + public BdfList getMessageAsList(Transaction txn, MessageId m, + boolean canonical) throws DbException, FormatException { + return toList(db.getMessage(txn, m), canonical); } @Override @@ -313,8 +319,13 @@ class ClientHelperImpl implements ClientHelper { @Override public BdfList toList(byte[] b, int off, int len) throws FormatException { + return toList(b, off, len, true); + } + + private BdfList toList(byte[] b, int off, int len, boolean canonical) + throws FormatException { ByteArrayInputStream in = new ByteArrayInputStream(b, off, len); - BdfReader reader = bdfReaderFactory.createReader(in); + BdfReader reader = bdfReaderFactory.createReader(in, canonical); try { BdfList list = reader.readList(); if (!reader.eof()) throw new FormatException(); @@ -328,7 +339,7 @@ class ClientHelperImpl implements ClientHelper { @Override public BdfList toList(byte[] b) throws FormatException { - return toList(b, 0, b.length); + return toList(b, 0, b.length, true); } @Override @@ -336,6 +347,12 @@ class ClientHelperImpl implements ClientHelper { return toList(m.getBody()); } + @Override + public BdfList toList(Message m, boolean canonical) throws FormatException { + byte[] b = m.getBody(); + return toList(b, 0, b.length, canonical); + } + @Override public BdfList toList(Author a) { return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey()); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java index 48d61ca63..a106b1d1c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderFactoryImpl.java @@ -18,12 +18,18 @@ class BdfReaderFactoryImpl implements BdfReaderFactory { @Override public BdfReader createReader(InputStream in) { return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, - DEFAULT_MAX_BUFFER_SIZE); + DEFAULT_MAX_BUFFER_SIZE, true); + } + + @Override + public BdfReader createReader(InputStream in, boolean canonical) { + return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, + DEFAULT_MAX_BUFFER_SIZE, canonical); } @Override public BdfReader createReader(InputStream in, int nestedLimit, - int maxBufferSize) { - return new BdfReaderImpl(in, nestedLimit, maxBufferSize); + int maxBufferSize, boolean canonical) { + return new BdfReaderImpl(in, nestedLimit, maxBufferSize, canonical); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java index d5badb88e..71734ec62 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java @@ -39,15 +39,18 @@ class BdfReaderImpl implements BdfReader { private final InputStream in; private final int nestedLimit, maxBufferSize; + private final boolean canonical; private boolean hasLookahead = false, eof = false; private byte next; private byte[] buf = new byte[8]; - BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize) { + BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize, + boolean canonical) { this.in = in; this.nestedLimit = nestedLimit; this.maxBufferSize = maxBufferSize; + this.canonical = canonical; } private void readLookahead() throws IOException { @@ -188,13 +191,22 @@ class BdfReaderImpl implements BdfReader { private short readInt16() throws IOException { readIntoBuffer(2); - return (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF)); + short value = (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF)); + if (canonical && value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { + // Value could have been encoded as an INT_8 + throw new FormatException(); + } + return value; } private int readInt32() throws IOException { readIntoBuffer(4); int value = 0; for (int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8); + if (canonical && value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { + // Value could have been encoded as an INT_16 + throw new FormatException(); + } return value; } @@ -202,6 +214,11 @@ class BdfReaderImpl implements BdfReader { readIntoBuffer(8); long value = 0; for (int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8); + if (canonical && value >= Integer.MIN_VALUE && + value <= Integer.MAX_VALUE) { + // Value could have been encoded as an INT_32 + throw new FormatException(); + } return value; } @@ -382,8 +399,16 @@ class BdfReaderImpl implements BdfReader { if (level > nestedLimit) throw new FormatException(); BdfDictionary dictionary = new BdfDictionary(); readDictionaryStart(); - while (!hasDictionaryEnd()) - dictionary.put(readString(), readObject(level + 1)); + String prevKey = null; + while (!hasDictionaryEnd()) { + String key = readString(); + if (canonical && prevKey != null && key.compareTo(prevKey) <= 0) { + // Keys not unique and sorted + throw new FormatException(); + } + dictionary.put(key, readObject(level + 1)); + prevKey = key; + } readDictionaryEnd(); return dictionary; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java index aa862e572..54cc732ac 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java @@ -7,14 +7,15 @@ import org.briarproject.nullsafety.NotNullByDefault; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; +import static java.util.Collections.sort; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.bramble.data.Types.DICTIONARY; import static org.briarproject.bramble.data.Types.END; @@ -33,6 +34,7 @@ import static org.briarproject.bramble.data.Types.STRING_16; import static org.briarproject.bramble.data.Types.STRING_32; import static org.briarproject.bramble.data.Types.STRING_8; import static org.briarproject.bramble.data.Types.TRUE; +import static org.briarproject.bramble.util.StringUtils.UTF_8; @NotThreadSafe @NotNullByDefault @@ -113,7 +115,7 @@ class BdfWriterImpl implements BdfWriter { @Override public void writeString(String s) throws IOException { - byte[] b = s.getBytes("UTF-8"); + byte[] b = s.getBytes(UTF_8); if (b.length <= Byte.MAX_VALUE) { out.write(STRING_8); out.write((byte) b.length); @@ -161,8 +163,8 @@ class BdfWriterImpl implements BdfWriter { else if (o instanceof String) writeString((String) o); else if (o instanceof byte[]) writeRaw((byte[]) o); else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes()); - else if (o instanceof List) writeList((List) o); - else if (o instanceof Map) writeDictionary((Map) o); + else if (o instanceof List) writeList((List) o); + else if (o instanceof Map) writeDictionary((Map) o); else throw new FormatException(); } @@ -179,10 +181,16 @@ class BdfWriterImpl implements BdfWriter { @Override public void writeDictionary(Map m) throws IOException { out.write(DICTIONARY); - for (Entry e : m.entrySet()) { - if (!(e.getKey() instanceof String)) throw new FormatException(); - writeString((String) e.getKey()); - writeObject(e.getValue()); + // Write entries in canonical order + List keys = new ArrayList<>(m.size()); + for (Object k : m.keySet()) { + if (!(k instanceof String)) throw new FormatException(); + keys.add((String) k); + } + sort(keys); + for (String key : keys) { + writeString(key); + writeObject(m.get(key)); } out.write(END); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java index 7f17fed48..e1641d6e9 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java @@ -201,7 +201,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, // Retrieve and parse the latest local properties for (Entry e : latest.entrySet()) { BdfList message = clientHelper.getMessageAsList(txn, - e.getValue().messageId); + e.getValue().messageId, false); local.put(e.getKey(), parseProperties(message)); } return local; @@ -222,7 +222,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, if (latest != null) { // Retrieve and parse the latest local properties BdfList message = clientHelper.getMessageAsList(txn, - latest.messageId); + latest.messageId, false); p = parseProperties(message); } return p == null ? new TransportProperties() : p; @@ -252,7 +252,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, local = new TransportProperties(); } else { BdfList message = clientHelper.getMessageAsList(txn, - latest.messageId); + latest.messageId, false); local = parseProperties(message); } storeLocalProperties(txn, c, t, local); @@ -272,8 +272,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, remote = new TransportProperties(); } else { // Retrieve and parse the latest remote properties - BdfList message = - clientHelper.getMessageAsList(txn, latest.messageId); + BdfList message = clientHelper.getMessageAsList(txn, + latest.messageId, false); remote = parseProperties(message); } // Merge in any discovered properties @@ -317,7 +317,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, changed = true; } else { BdfList message = clientHelper.getMessageAsList(txn, - latest.messageId); + latest.messageId, false); TransportProperties old = parseProperties(message); merged = new TransportProperties(old); for (Entry e : p.entrySet()) { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java index d0dd2b91b..6a4c0abb4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyValidator.java @@ -27,7 +27,10 @@ class TransportPropertyValidator extends BdfMessageValidator { TransportPropertyValidator(ClientHelper clientHelper, MetadataEncoder metadataEncoder, Clock clock) { - super(clientHelper, metadataEncoder, clock); + // Accept transport properties in non-canonical form + // TODO: Remove this after a reasonable migration period + // (added 2023-02-17) + super(clientHelper, metadataEncoder, clock, false); } @Override diff --git a/bramble-core/src/test/java/org/briarproject/bramble/client/BdfMessageValidatorTest.java b/bramble-core/src/test/java/org/briarproject/bramble/client/BdfMessageValidatorTest.java index a6b93c6cc..6794367df 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/client/BdfMessageValidatorTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/client/BdfMessageValidatorTest.java @@ -56,7 +56,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(clock).currentTimeMillis(); will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE)); - oneOf(clientHelper).toList(message.getBody()); + oneOf(clientHelper).toList(message, true); will(returnValue(body)); oneOf(metadataEncoder).encode(dictionary); will(returnValue(meta)); @@ -86,7 +86,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(clock).currentTimeMillis(); will(returnValue(timestamp)); - oneOf(clientHelper).toList(shortMessage.getBody()); + oneOf(clientHelper).toList(shortMessage, true); will(returnValue(body)); oneOf(metadataEncoder).encode(dictionary); will(returnValue(meta)); @@ -114,7 +114,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(clock).currentTimeMillis(); will(returnValue(timestamp)); - oneOf(clientHelper).toList(message.getBody()); + oneOf(clientHelper).toList(message, true); will(throwException(new FormatException())); }}); @@ -126,7 +126,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase { context.checking(new Expectations() {{ oneOf(clock).currentTimeMillis(); will(returnValue(timestamp)); - oneOf(clientHelper).toList(message.getBody()); + oneOf(clientHelper).toList(message, true); will(returnValue(body)); }}); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java index 7c39128a1..a4f8149f1 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java @@ -546,7 +546,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase { context.checking(new Expectations() {{ oneOf(bdfReaderFactory) - .createReader(with(any(InputStream.class))); + .createReader(with(any(InputStream.class)), with(true)); will(returnValue(bdfReader)); oneOf(bdfReader).readList(); will(returnValue(list)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java index f83a6bc6f..fcbf6bfb9 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplFuzzingTest.java @@ -32,7 +32,7 @@ public class BdfReaderImplFuzzingTest extends BrambleTestCase { buf[1] = 0x14; // Length 20 bytes in.reset(); BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, - DEFAULT_MAX_BUFFER_SIZE); + DEFAULT_MAX_BUFFER_SIZE, true); try { int length = r.readString().length(); assertTrue(length <= 20); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java index f59584b57..ebd0af441 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java @@ -11,6 +11,7 @@ import java.io.ByteArrayInputStream; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE; import static org.briarproject.bramble.data.BdfReaderImpl.DEFAULT_NESTED_LIMIT; +import static org.briarproject.bramble.util.StringUtils.UTF_8; import static org.briarproject.bramble.util.StringUtils.fromHexString; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.toHexString; @@ -88,6 +89,18 @@ public class BdfReaderImplTest extends BrambleTestCase { assertTrue(r.eof()); } + @Test(expected = FormatException.class) + public void testReadLong16CouldHaveBeenLong8Max() throws Exception { + setContents("22" + "007F"); + r.readLong(); + } + + @Test(expected = FormatException.class) + public void testReadLong16CouldHaveBeenLong8Min() throws Exception { + setContents("22" + "FF80"); + r.readLong(); + } + @Test public void testSkipLong16() throws Exception { setContents("22" + "0080"); @@ -106,6 +119,18 @@ public class BdfReaderImplTest extends BrambleTestCase { assertTrue(r.eof()); } + @Test(expected = FormatException.class) + public void testReadLong32CouldHaveBeenLong16Max() throws Exception { + setContents("24" + "00007FFF"); + r.readLong(); + } + + @Test(expected = FormatException.class) + public void testReadLong32CouldHaveBeenLong16Min() throws Exception { + setContents("24" + "FFFF8000"); + r.readLong(); + } + @Test public void testSkipLong32() throws Exception { setContents("24" + "00008000"); @@ -124,6 +149,18 @@ public class BdfReaderImplTest extends BrambleTestCase { assertTrue(r.eof()); } + @Test(expected = FormatException.class) + public void testReadLong64CouldHaveBeenLong32Max() throws Exception { + setContents("28" + "000000007FFFFFFF"); + r.readLong(); + } + + @Test(expected = FormatException.class) + public void testReadLong64CouldHaveBeenLong32Min() throws Exception { + setContents("28" + "FFFFFFFF80000000"); + r.readLong(); + } + @Test public void testSkipLong() throws Exception { setContents("28" + "0000000080000000"); @@ -162,7 +199,7 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testReadString8() throws Exception { String longest = getRandomString(Byte.MAX_VALUE); - String longHex = toHexString(longest.getBytes("UTF-8")); + String longHex = toHexString(longest.getBytes(UTF_8)); // "foo", the empty string, and 127 random letters setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "7F" + longHex); @@ -186,7 +223,7 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testSkipString8() throws Exception { String longest = getRandomString(Byte.MAX_VALUE); - String longHex = toHexString(longest.getBytes("UTF-8")); + String longHex = toHexString(longest.getBytes(UTF_8)); // "foo", the empty string, and 127 random letters setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "7F" + longHex); @@ -199,9 +236,9 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testReadString16() throws Exception { String shortest = getRandomString(Byte.MAX_VALUE + 1); - String shortHex = toHexString(shortest.getBytes("UTF-8")); + String shortHex = toHexString(shortest.getBytes(UTF_8)); String longest = getRandomString(Short.MAX_VALUE); - String longHex = toHexString(longest.getBytes("UTF-8")); + String longHex = toHexString(longest.getBytes(UTF_8)); // 128 random letters and 2^15 -1 random letters setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex); assertEquals(shortest, r.readString()); @@ -213,7 +250,7 @@ public class BdfReaderImplTest extends BrambleTestCase { public void testReadString16ChecksMaxLength() throws Exception { int maxBufferSize = Byte.MAX_VALUE + 1; String valid = getRandomString(Byte.MAX_VALUE + 1); - String validHex = toHexString(valid.getBytes("UTF-8")); + String validHex = toHexString(valid.getBytes(UTF_8)); String invalidhex = validHex + "20"; // 128 random letters, the same plus a space setContents("42" + "0080" + validHex @@ -223,12 +260,20 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readString(); } + @Test(expected = FormatException.class) + public void testReadString16CouldHaveBeenString8() throws Exception { + String longest = getRandomString(Byte.MAX_VALUE); + String longHex = toHexString(longest.getBytes(UTF_8)); + setContents("42" + "007F" + longHex); + r.readString(); + } + @Test public void testSkipString16() throws Exception { String shortest = getRandomString(Byte.MAX_VALUE + 1); - String shortHex = toHexString(shortest.getBytes("UTF-8")); + String shortHex = toHexString(shortest.getBytes(UTF_8)); String longest = getRandomString(Short.MAX_VALUE); - String longHex = toHexString(longest.getBytes("UTF-8")); + String longHex = toHexString(longest.getBytes(UTF_8)); // 128 random letters and 2^15 - 1 random letters setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex); r.skipString(); @@ -239,7 +284,7 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testReadString32() throws Exception { String shortest = getRandomString(Short.MAX_VALUE + 1); - String shortHex = toHexString(shortest.getBytes("UTF-8")); + String shortHex = toHexString(shortest.getBytes(UTF_8)); // 2^15 random letters setContents("44" + "00008000" + shortHex); assertEquals(shortest, r.readString()); @@ -250,7 +295,7 @@ public class BdfReaderImplTest extends BrambleTestCase { public void testReadString32ChecksMaxLength() throws Exception { int maxBufferSize = Short.MAX_VALUE + 1; String valid = getRandomString(maxBufferSize); - String validHex = toHexString(valid.getBytes("UTF-8")); + String validHex = toHexString(valid.getBytes(UTF_8)); String invalidHex = validHex + "20"; // 2^15 random letters, the same plus a space setContents("44" + "00008000" + validHex + @@ -260,10 +305,18 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readString(); } + @Test(expected = FormatException.class) + public void testReadString32CouldHaveBeenString16() throws Exception { + String longest = getRandomString(Short.MAX_VALUE); + String longHex = toHexString(longest.getBytes(UTF_8)); + setContents("44" + "00007FFF" + longHex); + r.readString(); + } + @Test public void testSkipString32() throws Exception { String shortest = getRandomString(Short.MAX_VALUE + 1); - String shortHex = toHexString(shortest.getBytes("UTF-8")); + String shortHex = toHexString(shortest.getBytes(UTF_8)); // 2^15 random letters, twice setContents("44" + "00008000" + shortHex + "44" + "00008000" + shortHex); @@ -275,7 +328,7 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testReadUtf8String() throws Exception { String unicode = "\uFDD0\uFDD1\uFDD2\uFDD3"; - String hex = toHexString(unicode.getBytes("UTF-8")); + String hex = toHexString(unicode.getBytes(UTF_8)); // STRING_8 tag, "foo", the empty string, and the test string setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "0C" + hex); assertEquals("foo", r.readString()); @@ -348,6 +401,14 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readRaw(); } + @Test(expected = FormatException.class) + public void testReadRaw16CouldHaveBeenRaw8() throws Exception { + byte[] longest = new byte[Byte.MAX_VALUE]; + String longHex = toHexString(longest); + setContents("52" + "007F" + longHex); + r.readRaw(); + } + @Test public void testSkipRaw16() throws Exception { byte[] shortest = new byte[Byte.MAX_VALUE + 1]; @@ -385,6 +446,14 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readRaw(); } + @Test(expected = FormatException.class) + public void testReadRaw32CouldHaveBeenRaw16() throws Exception { + byte[] longest = new byte[Short.MAX_VALUE]; + String longHex = toHexString(longest); + setContents("54" + "00007FFF" + longHex); + r.readRaw(); + } + @Test public void testSkipRaw32() throws Exception { byte[] shortest = new byte[Short.MAX_VALUE + 1]; @@ -465,9 +534,9 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testReadDictionary() throws Exception { - // A dictionary containing "foo" -> 123 and "bar" -> null - setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" + - "41" + "03" + "626172" + "00" + "80"); + // A dictionary containing "bar" -> null and "foo" -> 123 + setContents("70" + "41" + "03" + "626172" + "00" + + "41" + "03" + "666F6F" + "21" + "7B" + "80"); BdfDictionary dictionary = r.readDictionary(); assertEquals(2, dictionary.size()); assertTrue(dictionary.containsKey("foo")); @@ -557,10 +626,10 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test public void testNestedListWithinDepthLimit() throws Exception { // A list containing a list containing a list containing a list... - String lists = ""; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "60"; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "80"; - setContents(lists); + StringBuilder lists = new StringBuilder(); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("60"); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("80"); + setContents(lists.toString()); r.readList(); assertTrue(r.eof()); } @@ -568,23 +637,25 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test(expected = FormatException.class) public void testNestedListOutsideDepthLimit() throws Exception { // A list containing a list containing a list containing a list... - String lists = ""; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "60"; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "80"; - setContents(lists); + StringBuilder lists = new StringBuilder(); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("60"); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("80"); + setContents(lists.toString()); r.readList(); } @Test public void testNestedDictionaryWithinDepthLimit() throws Exception { // A dictionary containing a dictionary containing a dictionary... - String dicts = ""; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) - dicts += "70" + "41" + "03" + "666F6F"; - dicts += "11"; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) - dicts += "80"; - setContents(dicts); + StringBuilder dicts = new StringBuilder(); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) { + dicts.append("70").append("41").append("03").append("666F6F"); + } + dicts.append("11"); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) { + dicts.append("80"); + } + setContents(dicts.toString()); r.readDictionary(); assertTrue(r.eof()); } @@ -592,13 +663,15 @@ public class BdfReaderImplTest extends BrambleTestCase { @Test(expected = FormatException.class) public void testNestedDictionaryOutsideDepthLimit() throws Exception { // A dictionary containing a dictionary containing a dictionary... - String dicts = ""; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) - dicts += "70" + "41" + "03" + "666F6F"; - dicts += "11"; - for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) - dicts += "80"; - setContents(dicts); + StringBuilder dicts = new StringBuilder(); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) { + dicts.append("70").append("41").append("03").append("666F6F"); + } + dicts.append("11"); + for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) { + dicts.append("80"); + } + setContents(dicts.toString()); r.readDictionary(); } @@ -625,6 +698,6 @@ public class BdfReaderImplTest extends BrambleTestCase { private void setContents(String hex, int maxBufferSize) throws FormatException { ByteArrayInputStream in = new ByteArrayInputStream(fromHexString(hex)); - r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize); + r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize, true); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderWriterIntegrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderWriterIntegrationTest.java new file mode 100644 index 000000000..777aa2daf --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderWriterIntegrationTest.java @@ -0,0 +1,80 @@ +package org.briarproject.bramble.data; + +import org.briarproject.bramble.api.data.BdfDictionary; +import org.briarproject.bramble.api.data.BdfReader; +import org.briarproject.bramble.api.data.BdfWriter; +import org.briarproject.bramble.test.BrambleTestCase; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE; +import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_NESTED_LIMIT; +import static org.briarproject.bramble.util.StringUtils.fromHexString; +import static org.briarproject.bramble.util.StringUtils.toHexString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class BdfReaderWriterIntegrationTest extends BrambleTestCase { + + @Test + public void testConvertStringToCanonicalForm() throws Exception { + // 'foo' as a STRING_16 (not canonical, should be a STRING_8) + String hexIn = "42" + "0003" + "666F6F"; + InputStream in = new ByteArrayInputStream(fromHexString(hexIn)); + BdfReader r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, + DEFAULT_MAX_BUFFER_SIZE, false); // Accept non-canonical + String s = r.readString(); + assertEquals("foo", s); + assertTrue(r.eof()); + // Convert the string back to BDF + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BdfWriter w = new BdfWriterImpl(out); + w.writeString(s); + w.flush(); + String hexOut = toHexString(out.toByteArray()); + // The BDF should now be in canonical form + assertEquals("41" + "03" + "666F6F", hexOut); + } + + @Test + public void testConvertDictionaryToCanonicalForm() throws Exception { + // A dictionary with keys in non-canonical order: 'foo' then 'bar' + String hexIn = "70" + "41" + "03" + "666F6F" + "21" + "01" + + "41" + "03" + "626172" + "21" + "02" + "80"; + InputStream in = new ByteArrayInputStream(fromHexString(hexIn)); + BdfReader r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, + DEFAULT_MAX_BUFFER_SIZE, false); // Accept non-canonical + BdfDictionary d = r.readDictionary(); + assertEquals(2, d.size()); + assertTrue(r.eof()); + // The entries should be returned in canonical order + Iterator> it = d.entrySet().iterator(); + Entry first = it.next(); + assertEquals("bar", first.getKey()); + assertEquals(2L, first.getValue()); + Entry second = it.next(); + assertEquals("foo", second.getKey()); + assertEquals(1L, second.getValue()); + + // Convert a non-canonical map to BDF (use LinkedHashMap so we know + // the entries will be iterated over in non-canonical order) + Map m = new LinkedHashMap<>(); + m.put("foo", 1); + m.put("bar", 2); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BdfWriter w = new BdfWriterImpl(out); + w.writeDictionary(m); + w.flush(); + String hexOut = toHexString(out.toByteArray()); + // The entries should be in canonical order: 'bar' then 'foo' + assertEquals("70" + "41" + "03" + "626172" + "21" + "02" + + "41" + "03" + "666F6F" + "21" + "01" + "80", hexOut); + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java index 7c7396f6e..27251be97 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java @@ -404,7 +404,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, localGroup.getId()); will(returnValue(messageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); + oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false); will(returnValue(fooUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( fooPropertiesDict); @@ -471,7 +471,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, contactGroup2.getId()); will(returnValue(messageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); + oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false); will(returnValue(fooUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( fooPropertiesDict); @@ -526,7 +526,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, contactGroup.getId()); will(returnValue(messageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, updateId); + oneOf(clientHelper).getMessageAsList(txn, updateId, false); will(returnValue(update)); oneOf(clientHelper).parseAndValidateTransportProperties( fooPropertiesDict); @@ -564,7 +564,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, localGroup.getId()); will(returnValue(messageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, updateId); + oneOf(clientHelper).getMessageAsList(txn, updateId, false); will(returnValue(update)); oneOf(clientHelper).parseAndValidateTransportProperties( fooPropertiesDict); @@ -695,7 +695,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, localGroup.getId()); will(returnValue(localGroupMessageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId); + oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId, + false); will(returnValue(oldUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( oldPropertiesDict); @@ -760,7 +761,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { oneOf(clientHelper).getMessageMetadataAsDictionary(txn, localGroup.getId()); will(returnValue(localGroupMessageMetadata)); - oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId); + oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId, + false); will(returnValue(oldUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( oldPropertiesDict); @@ -819,12 +821,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase { localGroup.getId()); will(returnValue(messageMetadata)); // Retrieve and parse the latest local properties - oneOf(clientHelper).getMessageAsList(txn, fooVersion999); + oneOf(clientHelper).getMessageAsList(txn, fooVersion999, false); will(returnValue(fooUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( fooPropertiesDict); will(returnValue(fooProperties)); - oneOf(clientHelper).getMessageAsList(txn, barVersion3); + oneOf(clientHelper).getMessageAsList(txn, barVersion3, false); will(returnValue(barUpdate)); oneOf(clientHelper).parseAndValidateTransportProperties( barPropertiesDict); From 7a854e70cb9ec57f21a46df7fc52bad13487c010 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Sat, 18 Feb 2023 15:52:04 +0000 Subject: [PATCH 3/9] Add BdfReader methods for 32-bit ints. We use these a lot so it's convenient to have built-in support. Also make BdfReaderImpl and BdfWriterImpl final to enable compiler optimisations. --- .../bramble/api/data/BdfReader.java | 6 +++++ .../bramble/data/BdfReaderImpl.java | 27 ++++++++++++++++++- .../bramble/data/BdfWriterImpl.java | 2 +- .../bramble/data/BdfReaderImplTest.java | 25 ++++++++++++++++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java index ab81a39cb..7e1ff0e50 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java @@ -32,6 +32,12 @@ public interface BdfReader { void skipLong() throws IOException; + boolean hasInt() throws IOException; + + int readInt() throws IOException; + + void skipInt() throws IOException; + boolean hasDouble() throws IOException; double readDouble() throws IOException; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java index 71734ec62..72fb8bd21 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java @@ -33,7 +33,7 @@ import static org.briarproject.bramble.util.StringUtils.fromUtf8; @NotThreadSafe @NotNullByDefault -class BdfReaderImpl implements BdfReader { +final class BdfReaderImpl implements BdfReader { private static final byte[] EMPTY_BUFFER = new byte[0]; @@ -232,6 +232,31 @@ class BdfReaderImpl implements BdfReader { hasLookahead = false; } + @Override + public boolean hasInt() throws IOException { + if (!hasLookahead) readLookahead(); + if (eof) return false; + return next == INT_8 || next == INT_16 || next == INT_32; + } + + @Override + public int readInt() throws IOException { + if (!hasInt()) throw new FormatException(); + hasLookahead = false; + if (next == INT_8) return readInt8(); + if (next == INT_16) return readInt16(); + return readInt32(); + } + + @Override + public void skipInt() throws IOException { + if (!hasInt()) throw new FormatException(); + if (next == INT_8) skip(1); + else if (next == INT_16) skip(2); + else skip(4); + hasLookahead = false; + } + @Override public boolean hasDouble() throws IOException { if (!hasLookahead) readLookahead(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java index 54cc732ac..13812d6c1 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java @@ -38,7 +38,7 @@ import static org.briarproject.bramble.util.StringUtils.UTF_8; @NotThreadSafe @NotNullByDefault -class BdfWriterImpl implements BdfWriter { +final class BdfWriterImpl implements BdfWriter { private final OutputStream out; diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java index ebd0af441..2b09189b7 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java @@ -162,12 +162,35 @@ public class BdfReaderImplTest extends BrambleTestCase { } @Test - public void testSkipLong() throws Exception { + public void testSkipLong64() throws Exception { setContents("28" + "0000000080000000"); r.skipLong(); assertTrue(r.eof()); } + @Test + public void testReadInt() throws Exception { + setContents("21" + "7F" + "21" + "80" + + "22" + "7FFF" + "22" + "8000" + + "24" + "7FFFFFFF" + "24" + "80000000"); + assertEquals(Byte.MAX_VALUE, r.readInt()); + assertEquals(Byte.MIN_VALUE, r.readInt()); + assertEquals(Short.MAX_VALUE, r.readInt()); + assertEquals(Short.MIN_VALUE, r.readInt()); + assertEquals(Integer.MAX_VALUE, r.readInt()); + assertEquals(Integer.MIN_VALUE, r.readInt()); + assertTrue(r.eof()); + } + + @Test + public void testSkipInt() throws Exception { + setContents("21" + "7F" + "22" + "7FFF" + "24" + "7FFFFFFF"); + r.skipInt(); + r.skipInt(); + r.skipInt(); + assertTrue(r.eof()); + } + @Test public void testReadDouble() throws Exception { // http://babbage.cs.qc.edu/IEEE-754/Decimal.html From 63172ef2e4c91ccbd384e64b74b67789825bd36c Mon Sep 17 00:00:00 2001 From: akwizgran Date: Sat, 18 Feb 2023 15:54:47 +0000 Subject: [PATCH 4/9] Add 32-bit int methods to BdfList and BdfDictionary. We use these a lot so it's useful to have built-in support. Also refactor BdfList and BdfDictionary so the getters that take default values behave like the other getters. This simplifies the semantics and allows duplicated code to be removed. Add comprehensive tests for BdfList and BdfDictionary. --- .../bramble/api/data/BdfDictionary.java | 131 ++++--- .../bramble/api/data/BdfList.java | 146 ++++---- .../bramble/api/data/BdfDictionaryTest.java | 325 +++++++++++++++- .../bramble/api/data/BdfListTest.java | 348 ++++++++++++++---- .../bramble/client/ClientHelperImpl.java | 7 +- .../bramble/plugin/tcp/LanTcpPlugin.java | 2 +- .../agreement/SessionParserImpl.java | 9 +- .../TransportKeyAgreementManagerImpl.java | 4 +- .../TransportKeyAgreementValidator.java | 2 +- .../ClientVersioningManagerImpl.java | 8 +- .../versioning/ClientVersioningValidator.java | 4 +- .../bramble/plugin/tcp/LanTcpPluginTest.java | 2 +- .../attachment/AttachmentReaderImpl.java | 2 +- .../briar/avatar/AvatarManagerImpl.java | 2 +- .../briar/blog/BlogManagerImpl.java | 5 +- .../briar/blog/BlogPostFactoryImpl.java | 2 +- .../briar/blog/BlogPostValidator.java | 2 +- .../briar/client/MessageTrackerImpl.java | 4 +- .../introduction/IntroductionValidator.java | 2 +- .../briar/introduction/MessageParserImpl.java | 4 +- .../briar/introduction/SessionParserImpl.java | 35 +- .../briar/messaging/MessagingManagerImpl.java | 4 +- .../messaging/PrivateMessageValidator.java | 2 +- .../privategroup/GroupMessageValidator.java | 2 +- .../privategroup/PrivateGroupManagerImpl.java | 14 +- .../GroupInvitationManagerImpl.java | 9 +- .../invitation/GroupInvitationValidator.java | 2 +- .../invitation/MessageParserImpl.java | 4 +- .../invitation/SessionParser.java | 2 +- .../invitation/SessionParserImpl.java | 6 +- .../briar/sharing/MessageParserImpl.java | 4 +- .../briar/sharing/SessionParser.java | 2 +- .../briar/sharing/SessionParserImpl.java | 4 +- .../briar/sharing/SharingManagerImpl.java | 9 +- .../briar/sharing/SharingValidator.java | 2 +- .../GroupMessageValidatorTest.java | 2 +- 36 files changed, 820 insertions(+), 294 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java index c17c19bca..11d6f8a08 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfDictionary.java @@ -11,7 +11,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; @NotThreadSafe -public class BdfDictionary extends TreeMap { +public final class BdfDictionary extends TreeMap { public static final Object NULL_VALUE = new Object(); @@ -39,9 +39,9 @@ public class BdfDictionary extends TreeMap { } public Boolean getBoolean(String key) throws FormatException { - Object o = get(key); - if (o instanceof Boolean) return (Boolean) o; - throw new FormatException(); + Boolean value = getOptionalBoolean(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -52,19 +52,16 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public Boolean getBoolean(String key, Boolean defaultValue) { - Object o = get(key); - if (o instanceof Boolean) return (Boolean) o; - return defaultValue; + public Boolean getBoolean(String key, Boolean defaultValue) + throws FormatException { + Boolean value = getOptionalBoolean(key); + return value == null ? defaultValue : value; } public Long getLong(String key) throws FormatException { - Object o = get(key); - if (o instanceof Long) return (Long) o; - if (o instanceof Integer) return ((Integer) o).longValue(); - if (o instanceof Short) return ((Short) o).longValue(); - if (o instanceof Byte) return ((Byte) o).longValue(); - throw new FormatException(); + Long value = getOptionalLong(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -78,20 +75,37 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public Long getLong(String key, Long defaultValue) { - Object o = get(key); - if (o instanceof Long) return (Long) o; - if (o instanceof Integer) return ((Integer) o).longValue(); - if (o instanceof Short) return ((Short) o).longValue(); - if (o instanceof Byte) return ((Byte) o).longValue(); - return defaultValue; + public Long getLong(String key, Long defaultValue) throws FormatException { + Long value = getOptionalLong(key); + return value == null ? defaultValue : value; + } + + public Integer getInt(String key) throws FormatException { + Integer value = getOptionalInt(key); + if (value == null) throw new FormatException(); + return value; + } + + @Nullable + public Integer getOptionalInt(String key) throws FormatException { + Long value = getOptionalLong(key); + if (value == null) return null; + if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + throw new FormatException(); + } + return value.intValue(); + } + + public Integer getInt(String key, Integer defaultValue) + throws FormatException { + Integer value = getOptionalInt(key); + return value == null ? defaultValue : value; } public Double getDouble(String key) throws FormatException { - Object o = get(key); - if (o instanceof Double) return (Double) o; - if (o instanceof Float) return ((Float) o).doubleValue(); - throw new FormatException(); + Double value = getOptionalDouble(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -103,17 +117,16 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public Double getDouble(String key, Double defaultValue) { - Object o = get(key); - if (o instanceof Double) return (Double) o; - if (o instanceof Float) return ((Float) o).doubleValue(); - return defaultValue; + public Double getDouble(String key, Double defaultValue) + throws FormatException { + Double value = getOptionalDouble(key); + return value == null ? defaultValue : value; } public String getString(String key) throws FormatException { - Object o = get(key); - if (o instanceof String) return (String) o; - throw new FormatException(); + String value = getOptionalString(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -124,17 +137,16 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public String getString(String key, String defaultValue) { - Object o = get(key); - if (o instanceof String) return (String) o; - return defaultValue; + public String getString(String key, String defaultValue) + throws FormatException { + String value = getOptionalString(key); + return value == null ? defaultValue : value; } public byte[] getRaw(String key) throws FormatException { - Object o = get(key); - if (o instanceof byte[]) return (byte[]) o; - if (o instanceof Bytes) return ((Bytes) o).getBytes(); - throw new FormatException(); + byte[] value = getOptionalRaw(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -146,17 +158,16 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public byte[] getRaw(String key, byte[] defaultValue) { - Object o = get(key); - if (o instanceof byte[]) return (byte[]) o; - if (o instanceof Bytes) return ((Bytes) o).getBytes(); - return defaultValue; + public byte[] getRaw(String key, byte[] defaultValue) + throws FormatException { + byte[] value = getOptionalRaw(key); + return value == null ? defaultValue : value; } public BdfList getList(String key) throws FormatException { - Object o = get(key); - if (o instanceof BdfList) return (BdfList) o; - throw new FormatException(); + BdfList value = getOptionalList(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -167,16 +178,16 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public BdfList getList(String key, BdfList defaultValue) { - Object o = get(key); - if (o instanceof BdfList) return (BdfList) o; - return defaultValue; + public BdfList getList(String key, BdfList defaultValue) + throws FormatException { + BdfList value = getOptionalList(key); + return value == null ? defaultValue : value; } public BdfDictionary getDictionary(String key) throws FormatException { - Object o = get(key); - if (o instanceof BdfDictionary) return (BdfDictionary) o; - throw new FormatException(); + BdfDictionary value = getOptionalDictionary(key); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -188,9 +199,9 @@ public class BdfDictionary extends TreeMap { throw new FormatException(); } - public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) { - Object o = get(key); - if (o instanceof BdfDictionary) return (BdfDictionary) o; - return defaultValue; + public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) + throws FormatException { + BdfDictionary value = getOptionalDictionary(key); + return value == null ? defaultValue : value; } } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java index 21ec22728..6ba6747cc 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfList.java @@ -13,7 +13,7 @@ import javax.annotation.concurrent.NotThreadSafe; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; @NotThreadSafe -public class BdfList extends ArrayList { +public final class BdfList extends ArrayList { /** * Factory method for constructing lists inline. @@ -33,15 +33,15 @@ public class BdfList extends ArrayList { super(items); } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean isInRange(int index) { return index >= 0 && index < size(); } public Boolean getBoolean(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof Boolean) return (Boolean) o; - throw new FormatException(); + Boolean value = getOptionalBoolean(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -53,21 +53,16 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public Boolean getBoolean(int index, Boolean defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof Boolean) return (Boolean) o; - return defaultValue; + public Boolean getBoolean(int index, Boolean defaultValue) + throws FormatException { + Boolean value = getOptionalBoolean(index); + return value == null ? defaultValue : value; } public Long getLong(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof Long) return (Long) o; - if (o instanceof Integer) return ((Integer) o).longValue(); - if (o instanceof Short) return ((Short) o).longValue(); - if (o instanceof Byte) return ((Byte) o).longValue(); - throw new FormatException(); + Long value = getOptionalLong(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -82,22 +77,37 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public Long getLong(int index, Long defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof Long) return (Long) o; - if (o instanceof Integer) return ((Integer) o).longValue(); - if (o instanceof Short) return ((Short) o).longValue(); - if (o instanceof Byte) return ((Byte) o).longValue(); - return defaultValue; + public Long getLong(int index, Long defaultValue) throws FormatException { + Long value = getOptionalLong(index); + return value == null ? defaultValue : value; + } + + public Integer getInt(int index) throws FormatException { + Integer value = getOptionalInt(index); + if (value == null) throw new FormatException(); + return value; + } + + @Nullable + public Integer getOptionalInt(int index) throws FormatException { + Long value = getOptionalLong(index); + if (value == null) return null; + if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + throw new FormatException(); + } + return value.intValue(); + } + + public Integer getInt(int index, Integer defaultValue) + throws FormatException { + Integer value = getOptionalInt(index); + return value == null ? defaultValue : value; } public Double getDouble(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof Double) return (Double) o; - if (o instanceof Float) return ((Float) o).doubleValue(); - throw new FormatException(); + Double value = getOptionalDouble(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -110,19 +120,16 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public Double getDouble(int index, Double defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof Double) return (Double) o; - if (o instanceof Float) return ((Float) o).doubleValue(); - return defaultValue; + public Double getDouble(int index, Double defaultValue) + throws FormatException { + Double value = getOptionalDouble(index); + return value == null ? defaultValue : value; } public String getString(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof String) return (String) o; - throw new FormatException(); + String value = getOptionalString(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -134,19 +141,16 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public String getString(int index, String defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof String) return (String) o; - return defaultValue; + public String getString(int index, String defaultValue) + throws FormatException { + String value = getOptionalString(index); + return value == null ? defaultValue : value; } public byte[] getRaw(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof byte[]) return (byte[]) o; - if (o instanceof Bytes) return ((Bytes) o).getBytes(); - throw new FormatException(); + byte[] value = getOptionalRaw(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -159,19 +163,16 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public byte[] getRaw(int index, byte[] defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof byte[]) return (byte[]) o; - if (o instanceof Bytes) return ((Bytes) o).getBytes(); - return defaultValue; + public byte[] getRaw(int index, byte[] defaultValue) + throws FormatException { + byte[] value = getOptionalRaw(index); + return value == null ? defaultValue : value; } public BdfList getList(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof BdfList) return (BdfList) o; - throw new FormatException(); + BdfList value = getOptionalList(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -183,18 +184,16 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public BdfList getList(int index, BdfList defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof BdfList) return (BdfList) o; - return defaultValue; + public BdfList getList(int index, BdfList defaultValue) + throws FormatException { + BdfList value = getOptionalList(index); + return value == null ? defaultValue : value; } public BdfDictionary getDictionary(int index) throws FormatException { - if (!isInRange(index)) throw new FormatException(); - Object o = get(index); - if (o instanceof BdfDictionary) return (BdfDictionary) o; - throw new FormatException(); + BdfDictionary value = getOptionalDictionary(index); + if (value == null) throw new FormatException(); + return value; } @Nullable @@ -207,10 +206,9 @@ public class BdfList extends ArrayList { throw new FormatException(); } - public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) { - if (!isInRange(index)) return defaultValue; - Object o = get(index); - if (o instanceof BdfDictionary) return (BdfDictionary) o; - return defaultValue; + public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) + throws FormatException { + BdfDictionary value = getOptionalDictionary(index); + return value == null ? defaultValue : value; } } diff --git a/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfDictionaryTest.java b/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfDictionaryTest.java index 17bb65116..274834cb3 100644 --- a/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfDictionaryTest.java +++ b/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfDictionaryTest.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.api.data; import org.briarproject.bramble.api.Bytes; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Test; @@ -8,9 +9,12 @@ import java.util.Collections; import java.util.Iterator; import java.util.Map.Entry; +import static java.lang.Boolean.TRUE; +import static java.util.Collections.singletonMap; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class BdfDictionaryTest extends BrambleTestCase { @@ -19,20 +23,20 @@ public class BdfDictionaryTest extends BrambleTestCase { public void testConstructors() { assertEquals(Collections.emptyMap(), new BdfDictionary()); - assertEquals(Collections.singletonMap("foo", NULL_VALUE), - new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE))); + assertEquals(singletonMap("foo", NULL_VALUE), + new BdfDictionary(singletonMap("foo", NULL_VALUE))); } @Test public void testFactoryMethod() { assertEquals(Collections.emptyMap(), BdfDictionary.of()); - assertEquals(Collections.singletonMap("foo", NULL_VALUE), + assertEquals(singletonMap("foo", NULL_VALUE), BdfDictionary.of(new BdfEntry("foo", NULL_VALUE))); } @Test - public void testIntegerPromotion() throws Exception { + public void testLongPromotion() throws Exception { BdfDictionary d = new BdfDictionary(); d.put("foo", (byte) 1); d.put("bar", (short) 2); @@ -44,6 +48,33 @@ public class BdfDictionaryTest extends BrambleTestCase { assertEquals(Long.valueOf(4), d.getLong("bam")); } + @Test + public void testIntPromotionAndDemotion() throws Exception { + BdfDictionary d = new BdfDictionary(); + d.put("foo", (byte) 1); + d.put("bar", (short) 2); + d.put("baz", 3); + d.put("bam", 4L); + assertEquals(Integer.valueOf(1), d.getInt("foo")); + assertEquals(Integer.valueOf(2), d.getInt("bar")); + assertEquals(Integer.valueOf(3), d.getInt("baz")); + assertEquals(Integer.valueOf(4), d.getInt("bam")); + } + + @Test(expected = FormatException.class) + public void testIntUnderflow() throws Exception { + BdfDictionary d = + BdfDictionary.of(new BdfEntry("foo", Integer.MIN_VALUE - 1L)); + d.getInt("foo"); + } + + @Test(expected = FormatException.class) + public void testIntOverflow() throws Exception { + BdfDictionary d = + BdfDictionary.of(new BdfEntry("foo", Integer.MAX_VALUE + 1L)); + d.getInt("foo"); + } + @Test public void testFloatPromotion() throws Exception { BdfDictionary d = new BdfDictionary(); @@ -67,7 +98,7 @@ public class BdfDictionaryTest extends BrambleTestCase { } @Test - public void testKeySetIteratorIsOrderedByKeys() throws Exception { + public void testKeySetIteratorIsOrderedByKeys() { BdfDictionary d = new BdfDictionary(); d.put("a", 1); d.put("d", 4); @@ -86,7 +117,7 @@ public class BdfDictionaryTest extends BrambleTestCase { } @Test - public void testValuesIteratorIsOrderedByKeys() throws Exception { + public void testValuesIteratorIsOrderedByKeys() { BdfDictionary d = new BdfDictionary(); d.put("a", 1); d.put("d", 4); @@ -105,7 +136,7 @@ public class BdfDictionaryTest extends BrambleTestCase { } @Test - public void testEntrySetIteratorIsOrderedByKeys() throws Exception { + public void testEntrySetIteratorIsOrderedByKeys() { BdfDictionary d = new BdfDictionary(); d.put("a", 1); d.put("d", 4); @@ -130,4 +161,284 @@ public class BdfDictionaryTest extends BrambleTestCase { assertEquals("d", e.getKey()); assertEquals(4, e.getValue()); } + + @Test(expected = FormatException.class) + public void testMissingValueForBooleanThrowsFormatException() + throws Exception { + new BdfDictionary().getBoolean("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForLongThrowsFormatException() + throws Exception { + new BdfDictionary().getLong("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForIntThrowsFormatException() throws Exception { + new BdfDictionary().getInt("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForDoubleThrowsFormatException() + throws Exception { + new BdfDictionary().getDouble("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForStringThrowsFormatException() + throws Exception { + new BdfDictionary().getString("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForRawThrowsFormatException() throws Exception { + new BdfDictionary().getRaw("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForListThrowsFormatException() + throws Exception { + new BdfDictionary().getList("foo"); + } + + @Test(expected = FormatException.class) + public void testMissingValueForDictionaryThrowsFormatException() + throws Exception { + new BdfDictionary().getDictionary("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForBooleanThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getBoolean("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForLongThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getLong("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForIntThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getInt("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForDoubleThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getDouble("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForStringThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getString("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForRawThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getRaw("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForListThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getList("foo"); + } + + @Test(expected = FormatException.class) + public void testNullValueForDictionaryThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getDictionary("foo"); + } + + @Test + public void testOptionalMethodsReturnNullForMissingValue() + throws Exception { + testOptionalMethodsReturnNull(new BdfDictionary()); + } + + @Test + public void testOptionalMethodsReturnNullForNullValue() throws Exception { + BdfDictionary d = BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)); + testOptionalMethodsReturnNull(d); + } + + private void testOptionalMethodsReturnNull(BdfDictionary d) + throws Exception { + assertNull(d.getOptionalBoolean("foo")); + assertNull(d.getOptionalLong("foo")); + assertNull(d.getOptionalInt("foo")); + assertNull(d.getOptionalDouble("foo")); + assertNull(d.getOptionalString("foo")); + assertNull(d.getOptionalRaw("foo")); + assertNull(d.getOptionalList("foo")); + assertNull(d.getOptionalDictionary("foo")); + } + + @Test + public void testDefaultMethodsReturnDefaultForMissingValue() + throws Exception { + testDefaultMethodsReturnDefault(new BdfDictionary()); + } + + @Test + public void testDefaultMethodsReturnDefaultForNullValue() throws Exception { + BdfDictionary d = BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)); + testDefaultMethodsReturnDefault(d); + } + + private void testDefaultMethodsReturnDefault(BdfDictionary d) + throws Exception { + assertEquals(TRUE, d.getBoolean("foo", TRUE)); + assertEquals(Long.valueOf(123L), d.getLong("foo", 123L)); + assertEquals(Integer.valueOf(123), d.getInt("foo", 123)); + assertEquals(Double.valueOf(123D), d.getDouble("foo", 123D)); + assertEquals("123", d.getString("foo", "123")); + byte[] defaultRaw = {1, 2, 3}; + assertArrayEquals(defaultRaw, d.getRaw("foo", defaultRaw)); + BdfList defaultList = BdfList.of(1, 2, 3); + assertEquals(defaultList, d.getList("foo", defaultList)); + BdfDictionary defaultDict = BdfDictionary.of(new BdfEntry("123", 123)); + assertEquals(defaultDict, d.getDictionary("foo", defaultDict)); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForBooleanThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getBoolean("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalBooleanThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalBoolean("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultBooleanThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getBoolean("foo", true); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForLongThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getLong("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalLongThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getOptionalLong("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultLongThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getLong("foo", 1L); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForIntThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getInt("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalIntThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getOptionalInt("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultIntThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 1.23)).getInt("foo", 1); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDoubleThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getDouble("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalDoubleThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalDouble("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultDoubleThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getDouble("foo", 1D); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForStringThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getString("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalStringThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalString("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultStringThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getString("foo", ""); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForRawThrowsFormatException() throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getRaw("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalRawThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalRaw("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultRawThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getRaw("foo", new byte[0]); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForListThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getList("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalListThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalList("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultListThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getList("foo", + new BdfList()); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDictionaryThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getDictionary("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalDictionaryThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalDictionary("foo"); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultDictionaryThrowsFormatException() + throws Exception { + BdfDictionary.of(new BdfEntry("foo", 123)).getDictionary("foo", + new BdfDictionary()); + } } diff --git a/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfListTest.java b/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfListTest.java index 55fbf39db..7ee0ba799 100644 --- a/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfListTest.java +++ b/bramble-api/src/test/java/org/briarproject/bramble/api/data/BdfListTest.java @@ -5,31 +5,31 @@ import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Test; -import java.util.Arrays; -import java.util.Collections; - +import static java.lang.Boolean.TRUE; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; public class BdfListTest extends BrambleTestCase { @Test public void testConstructors() { - assertEquals(Collections.emptyList(), new BdfList()); - assertEquals(Arrays.asList(1, 2, NULL_VALUE), - new BdfList(Arrays.asList(1, 2, NULL_VALUE))); + assertEquals(emptyList(), new BdfList()); + assertEquals(asList(1, 2, NULL_VALUE), + new BdfList(asList(1, 2, NULL_VALUE))); } @Test public void testFactoryMethod() { - assertEquals(Collections.emptyList(), BdfList.of()); - assertEquals(Arrays.asList(1, 2, NULL_VALUE), - BdfList.of(1, 2, NULL_VALUE)); + assertEquals(emptyList(), BdfList.of()); + assertEquals(asList(1, 2, NULL_VALUE), BdfList.of(1, 2, NULL_VALUE)); } @Test - public void testIntegerPromotion() throws Exception { + public void testLongPromotion() throws Exception { BdfList list = new BdfList(); list.add((byte) 1); list.add((short) 2); @@ -41,6 +41,31 @@ public class BdfListTest extends BrambleTestCase { assertEquals(Long.valueOf(4), list.getLong(3)); } + @Test + public void testIntPromotionAndDemotion() throws Exception { + BdfList list = new BdfList(); + list.add((byte) 1); + list.add((short) 2); + list.add(3); + list.add(4L); + assertEquals(Integer.valueOf(1), list.getInt(0)); + assertEquals(Integer.valueOf(2), list.getInt(1)); + assertEquals(Integer.valueOf(3), list.getInt(2)); + assertEquals(Integer.valueOf(4), list.getInt(3)); + } + + @Test(expected = FormatException.class) + public void testIntUnderflow() throws Exception { + BdfList list = BdfList.of(Integer.MIN_VALUE - 1L); + list.getInt(0); + } + + @Test(expected = FormatException.class) + public void testIntOverflow() throws Exception { + BdfList list = BdfList.of(Integer.MAX_VALUE + 1L); + list.getInt(0); + } + @Test public void testFloatPromotion() throws Exception { BdfList list = new BdfList(); @@ -63,61 +88,6 @@ public class BdfListTest extends BrambleTestCase { assertArrayEquals(new byte[123], second); } - @Test - @SuppressWarnings("ConstantConditions") - public void testIndexOutOfBoundsReturnsDefaultValue() throws Exception { - BdfList list = BdfList.of(1, 2, 3); - boolean defaultBoolean = true; - assertEquals(defaultBoolean, list.getBoolean(-1, defaultBoolean)); - assertEquals(defaultBoolean, list.getBoolean(3, defaultBoolean)); - Long defaultLong = 123L; - assertEquals(defaultLong, list.getLong(-1, defaultLong)); - assertEquals(defaultLong, list.getLong(3, defaultLong)); - Double defaultDouble = 1.23; - assertEquals(defaultDouble, list.getDouble(-1, defaultDouble)); - assertEquals(defaultDouble, list.getDouble(3, defaultDouble)); - String defaultString = "123"; - assertEquals(defaultString, list.getString(-1, defaultString)); - assertEquals(defaultString, list.getString(3, defaultString)); - byte[] defaultBytes = new byte[] {1, 2, 3}; - assertArrayEquals(defaultBytes, list.getRaw(-1, defaultBytes)); - assertArrayEquals(defaultBytes, list.getRaw(3, defaultBytes)); - BdfList defaultList = BdfList.of(1, 2, 3); - assertEquals(defaultList, list.getList(-1, defaultList)); - assertEquals(defaultList, list.getList(3, defaultList)); - BdfDictionary defaultDict = BdfDictionary.of( - new BdfEntry("1", 1), - new BdfEntry("2", 2), - new BdfEntry("3", 3) - ); - assertEquals(defaultDict, list.getDictionary(-1, defaultDict)); - assertEquals(defaultDict, list.getDictionary(3, defaultDict)); - } - - @Test - @SuppressWarnings("ConstantConditions") - public void testWrongTypeReturnsDefaultValue() throws Exception { - BdfList list = BdfList.of(1, 2, 3, true); - boolean defaultBoolean = true; - assertEquals(defaultBoolean, list.getBoolean(0, defaultBoolean)); - Long defaultLong = 123L; - assertEquals(defaultLong, list.getLong(3, defaultLong)); - Double defaultDouble = 1.23; - assertEquals(defaultDouble, list.getDouble(0, defaultDouble)); - String defaultString = "123"; - assertEquals(defaultString, list.getString(0, defaultString)); - byte[] defaultBytes = new byte[] {1, 2, 3}; - assertArrayEquals(defaultBytes, list.getRaw(0, defaultBytes)); - BdfList defaultList = BdfList.of(1, 2, 3); - assertEquals(defaultList, list.getList(0, defaultList)); - BdfDictionary defaultDict = BdfDictionary.of( - new BdfEntry("1", 1), - new BdfEntry("2", 2), - new BdfEntry("3", 3) - ); - assertEquals(defaultDict, list.getDictionary(0, defaultDict)); - } - @Test(expected = FormatException.class) public void testNegativeIndexForBooleanThrowsFormatException() throws Exception { @@ -130,6 +100,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalBoolean(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultBooleanThrowsFormatException() + throws Exception { + new BdfList().getBoolean(-1, true); + } + @Test(expected = FormatException.class) public void testNegativeIndexForLongThrowsFormatException() throws Exception { @@ -142,6 +118,30 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalLong(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultLongThrowsFormatException() + throws Exception { + new BdfList().getLong(-1, 1L); + } + + @Test(expected = FormatException.class) + public void testNegativeIndexForIntThrowsFormatException() + throws Exception { + new BdfList().getInt(-1); + } + + @Test(expected = FormatException.class) + public void testNegativeIndexForOptionalIntThrowsFormatException() + throws Exception { + new BdfList().getOptionalInt(-1); + } + + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultIntThrowsFormatException() + throws Exception { + new BdfList().getInt(-1, 1); + } + @Test(expected = FormatException.class) public void testNegativeIndexForDoubleThrowsFormatException() throws Exception { @@ -154,6 +154,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalDouble(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultDoubleThrowsFormatException() + throws Exception { + new BdfList().getDouble(-1, 1D); + } + @Test(expected = FormatException.class) public void testNegativeIndexForStringThrowsFormatException() throws Exception { @@ -166,6 +172,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalString(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultStringThrowsFormatException() + throws Exception { + new BdfList().getString(-1, ""); + } + @Test(expected = FormatException.class) public void testNegativeIndexForRawThrowsFormatException() throws Exception { @@ -178,6 +190,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalRaw(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultRawThrowsFormatException() + throws Exception { + new BdfList().getRaw(-1, new byte[0]); + } + @Test(expected = FormatException.class) public void testNegativeIndexForListThrowsFormatException() throws Exception { @@ -190,6 +208,11 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalList(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultListThrowsFormatException() + throws Exception { + new BdfList().getList(-1, new BdfList()); + } @Test(expected = FormatException.class) public void testNegativeIndexForDictionaryThrowsFormatException() @@ -203,6 +226,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalDictionary(-1); } + @Test(expected = FormatException.class) + public void testNegativeIndexForDefaultDictionaryThrowsFormatException() + throws Exception { + new BdfList().getDictionary(-1, new BdfDictionary()); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForBooleanThrowsFormatException() throws Exception { @@ -215,6 +244,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalBoolean(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultBooleanThrowsFormatException() + throws Exception { + new BdfList().getBoolean(0, true); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForLongThrowsFormatException() throws Exception { @@ -227,6 +262,30 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalLong(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultLongThrowsFormatException() + throws Exception { + new BdfList().getLong(0, 1L); + } + + @Test(expected = FormatException.class) + public void testTooLargeIndexForIntThrowsFormatException() + throws Exception { + new BdfList().getInt(0); + } + + @Test(expected = FormatException.class) + public void testTooLargeIndexForOptionalIntThrowsFormatException() + throws Exception { + new BdfList().getOptionalInt(0); + } + + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultIntThrowsFormatException() + throws Exception { + new BdfList().getInt(0, 1); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForDoubleThrowsFormatException() throws Exception { @@ -239,6 +298,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalDouble(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultDoubleThrowsFormatException() + throws Exception { + new BdfList().getDouble(0, 1D); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForStringThrowsFormatException() throws Exception { @@ -251,6 +316,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalString(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultStringThrowsFormatException() + throws Exception { + new BdfList().getString(0, ""); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForRawThrowsFormatException() throws Exception { @@ -263,6 +334,12 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalRaw(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultRawThrowsFormatException() + throws Exception { + new BdfList().getRaw(0, new byte[0]); + } + @Test(expected = FormatException.class) public void testTooLargeIndexForListThrowsFormatException() throws Exception { @@ -275,6 +352,11 @@ public class BdfListTest extends BrambleTestCase { new BdfList().getOptionalList(0); } + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultListThrowsFormatException() + throws Exception { + new BdfList().getList(0, new BdfList()); + } @Test(expected = FormatException.class) public void testTooLargeIndexForDictionaryThrowsFormatException() @@ -287,6 +369,13 @@ public class BdfListTest extends BrambleTestCase { throws Exception { new BdfList().getOptionalDictionary(0); } + + @Test(expected = FormatException.class) + public void testTooLargeIndexForDefaultDictionaryThrowsFormatException() + throws Exception { + new BdfList().getDictionary(0, new BdfDictionary()); + } + @Test(expected = FormatException.class) public void testWrongTypeForBooleanThrowsFormatException() throws Exception { @@ -299,6 +388,12 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(123).getOptionalBoolean(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultBooleanThrowsFormatException() + throws Exception { + BdfList.of(123).getBoolean(0, true); + } + @Test(expected = FormatException.class) public void testWrongTypeForLongThrowsFormatException() throws Exception { BdfList.of(1.23).getLong(0); @@ -310,6 +405,29 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(1.23).getOptionalLong(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultLongThrowsFormatException() + throws Exception { + BdfList.of(1.23).getLong(0, 1L); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForIntThrowsFormatException() throws Exception { + BdfList.of(1.23).getInt(0); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForOptionalIntThrowsFormatException() + throws Exception { + BdfList.of(1.23).getOptionalInt(0); + } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultIntThrowsFormatException() + throws Exception { + BdfList.of(1.23).getInt(0, 1); + } + @Test(expected = FormatException.class) public void testWrongTypeForDoubleThrowsFormatException() throws Exception { BdfList.of(123).getDouble(0); @@ -321,6 +439,12 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(123).getOptionalDouble(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultDoubleThrowsFormatException() + throws Exception { + BdfList.of(123).getDouble(0, 1D); + } + @Test(expected = FormatException.class) public void testWrongTypeForStringThrowsFormatException() throws Exception { BdfList.of(123).getString(0); @@ -332,6 +456,12 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(123).getOptionalString(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultStringThrowsFormatException() + throws Exception { + BdfList.of(123).getString(0, ""); + } + @Test(expected = FormatException.class) public void testWrongTypeForRawThrowsFormatException() throws Exception { BdfList.of(123).getRaw(0); @@ -343,6 +473,12 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(123).getOptionalRaw(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultRawThrowsFormatException() + throws Exception { + BdfList.of(123).getRaw(0, new byte[0]); + } + @Test(expected = FormatException.class) public void testWrongTypeForListThrowsFormatException() throws Exception { BdfList.of(123).getList(0); @@ -354,6 +490,11 @@ public class BdfListTest extends BrambleTestCase { BdfList.of(123).getOptionalList(0); } + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultListThrowsFormatException() + throws Exception { + BdfList.of(123).getList(0, new BdfList()); + } @Test(expected = FormatException.class) public void testWrongTypeForDictionaryThrowsFormatException() @@ -366,4 +507,81 @@ public class BdfListTest extends BrambleTestCase { throws Exception { BdfList.of(123).getOptionalDictionary(0); } + + @Test(expected = FormatException.class) + public void testWrongTypeForDefaultDictionaryThrowsFormatException() + throws Exception { + BdfList.of(123).getDictionary(0, new BdfDictionary()); + } + + @Test(expected = FormatException.class) + public void testNullValueForBooleanThrowsFormatException() + throws Exception { + BdfList.of(NULL_VALUE).getBoolean(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForLongThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getLong(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForIntThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getInt(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForDoubleThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getDouble(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForStringThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getString(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForRawThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getRaw(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForListThrowsFormatException() throws Exception { + BdfList.of(NULL_VALUE).getList(0); + } + + @Test(expected = FormatException.class) + public void testNullValueForDictionaryThrowsFormatException() + throws Exception { + BdfList.of(NULL_VALUE).getDictionary(0); + } + + @Test + public void testOptionalMethodsReturnNullForNullValue() throws Exception { + BdfList list = BdfList.of(NULL_VALUE); + assertNull(list.getOptionalBoolean(0)); + assertNull(list.getOptionalLong(0)); + assertNull(list.getOptionalInt(0)); + assertNull(list.getOptionalDouble(0)); + assertNull(list.getOptionalString(0)); + assertNull(list.getOptionalRaw(0)); + assertNull(list.getOptionalList(0)); + assertNull(list.getOptionalDictionary(0)); + } + + @Test + public void testDefaultMethodsReturnDefaultForNullValue() throws Exception { + BdfList list = BdfList.of(NULL_VALUE); + assertEquals(TRUE, list.getBoolean(0, TRUE)); + assertEquals(Long.valueOf(123L), list.getLong(0, 123L)); + assertEquals(Integer.valueOf(123), list.getInt(0, 123)); + assertEquals(Double.valueOf(123D), list.getDouble(0, 123D)); + assertEquals("123", list.getString(0, "123")); + byte[] defaultRaw = {1, 2, 3}; + assertArrayEquals(defaultRaw, list.getRaw(0, defaultRaw)); + BdfList defaultList = BdfList.of(1, 2, 3); + assertEquals(defaultList, list.getList(0, defaultList)); + BdfDictionary defaultDict = BdfDictionary.of(new BdfEntry("123", 123)); + assertEquals(defaultDict, list.getDictionary(0, defaultDict)); + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java index 30d7d641b..34635142d 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java @@ -378,7 +378,7 @@ class ClientHelperImpl implements ClientHelper { public Author parseAndValidateAuthor(BdfList author) throws FormatException { checkSize(author, 3); - int formatVersion = author.getLong(0).intValue(); + int formatVersion = author.getInt(0); if (formatVersion != FORMAT_VERSION) throw new FormatException(); String name = author.getString(1); checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH); @@ -489,8 +489,7 @@ class ClientHelperImpl implements ClientHelper { if (element.size() != 2) { throw new FormatException(); } - list.add(new MailboxVersion(element.getLong(0).intValue(), - element.getLong(1).intValue())); + list.add(new MailboxVersion(element.getInt(0), element.getInt(1))); } // Sort the list of versions for easier comparison sort(list); @@ -503,7 +502,7 @@ class ClientHelperImpl implements ClientHelper { try { BdfDictionary meta = getGroupMetadataAsDictionary(txn, contactGroupId); - return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue()); + return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID)); } catch (FormatException e) { throw new DbException(e); // Invalid group metadata } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java index 1354900a7..a4250c7a8 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java @@ -419,7 +419,7 @@ class LanTcpPlugin extends TcpPlugin { private InetSocketAddress parseSocketAddress(BdfList descriptor) throws FormatException { byte[] address = descriptor.getRaw(1); - int port = descriptor.getLong(2).intValue(); + int port = descriptor.getInt(2); if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException(); try { InetAddress addr = InetAddress.getByAddress(address); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/SessionParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/SessionParserImpl.java index a0d18f380..160a134a8 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/SessionParserImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/SessionParserImpl.java @@ -32,8 +32,7 @@ class SessionParserImpl implements SessionParser { @Override public Session parseSession(BdfDictionary meta) throws FormatException { - State state = - State.fromValue(meta.getLong(SESSION_KEY_STATE).intValue()); + State state = State.fromValue(meta.getInt(SESSION_KEY_STATE)); MessageId lastLocalMessageId = null; byte[] lastLocalMessageIdBytes = @@ -56,9 +55,9 @@ class SessionParserImpl implements SessionParser { Long localTimestamp = meta.getOptionalLong(SESSION_KEY_LOCAL_TIMESTAMP); KeySetId keySetId = null; - Long keySetIdLong = meta.getOptionalLong(SESSION_KEY_KEY_SET_ID); - if (keySetIdLong != null) { - keySetId = new KeySetId(keySetIdLong.intValue()); + Integer keySetIdInt = meta.getOptionalInt(SESSION_KEY_KEY_SET_ID); + if (keySetIdInt != null) { + keySetId = new KeySetId(keySetIdInt); } return new Session(state, lastLocalMessageId, localKeyPair, diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementManagerImpl.java index 82a17af1e..d092709ae 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementManagerImpl.java @@ -177,8 +177,8 @@ class TransportKeyAgreementManagerImpl extends BdfIncomingMessageHook protected DeliveryAction incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, FormatException { - MessageType type = MessageType.fromValue( - meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue()); + MessageType type = + MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE)); TransportId t = new TransportId(meta.getString(MSG_KEY_TRANSPORT_ID)); if (LOG.isLoggable(INFO)) { LOG.info("Received " + type + " message for " + t); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementValidator.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementValidator.java index ca43a94c4..9133d3e8b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementValidator.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/agreement/TransportKeyAgreementValidator.java @@ -42,7 +42,7 @@ class TransportKeyAgreementValidator extends BdfMessageValidator { @Override protected BdfMessageContext validateMessage(Message m, Group g, BdfList body) throws FormatException { - MessageType type = MessageType.fromValue(body.getLong(0).intValue()); + MessageType type = MessageType.fromValue(body.getInt(0)); if (type == KEY) return validateKeyMessage(m.getTimestamp(), body); else if (type == ACTIVATE) return validateActivateMessage(body); else throw new AssertionError(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java index 232b71f1b..1dc50702e 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java @@ -301,8 +301,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, for (int i = 0; i < size; i++) { BdfList cv = body.getList(i); ClientId clientId = new ClientId(cv.getString(0)); - int majorVersion = cv.getLong(1).intValue(); - int minorVersion = cv.getLong(2).intValue(); + int majorVersion = cv.getInt(1); + int minorVersion = cv.getInt(2); parsed.add(new ClientVersion(clientId, majorVersion, minorVersion)); } return parsed; @@ -408,8 +408,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, throws FormatException { // Client ID, major version, minor version, active ClientId clientId = new ClientId(clientState.getString(0)); - int majorVersion = clientState.getLong(1).intValue(); - int minorVersion = clientState.getLong(2).intValue(); + int majorVersion = clientState.getInt(1); + int minorVersion = clientState.getInt(2); boolean active = clientState.getBoolean(3); return new ClientState(clientId, majorVersion, minorVersion, active); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningValidator.java b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningValidator.java index b6fbb0c5d..2171a3d75 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningValidator.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningValidator.java @@ -43,9 +43,9 @@ class ClientVersioningValidator extends BdfMessageValidator { checkSize(clientState, 4); String clientId = clientState.getString(0); checkLength(clientId, 1, MAX_CLIENT_ID_LENGTH); - int majorVersion = clientState.getLong(1).intValue(); + int majorVersion = clientState.getInt(1); if (majorVersion < 0) throw new FormatException(); - int minorVersion = clientState.getLong(2).intValue(); + int minorVersion = clientState.getInt(2); if (minorVersion < 0) throw new FormatException(); clientState.getBoolean(3); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index 6f6881599..6a890e33c 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -223,7 +223,7 @@ public class LanTcpPluginTest extends BrambleTestCase { assertTrue(addr instanceof Inet4Address); assertFalse(addr.isLoopbackAddress()); assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress()); - int port = descriptor.getLong(2).intValue(); + int port = descriptor.getInt(2); assertTrue(port > 0 && port < 65536); // The plugin should be listening on the port InetSocketAddress socketAddr = new InetSocketAddress(addr, port); diff --git a/briar-core/src/main/java/org/briarproject/briar/attachment/AttachmentReaderImpl.java b/briar-core/src/main/java/org/briarproject/briar/attachment/AttachmentReaderImpl.java index 69d5f963f..fb981a6b4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/attachment/AttachmentReaderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/attachment/AttachmentReaderImpl.java @@ -56,7 +56,7 @@ public class AttachmentReaderImpl implements AttachmentReader { String contentType = meta.getString(MSG_KEY_CONTENT_TYPE); if (!contentType.equals(h.getContentType())) throw new NoSuchMessageException(); - int offset = meta.getLong(MSG_KEY_DESCRIPTOR_LENGTH).intValue(); + int offset = meta.getInt(MSG_KEY_DESCRIPTOR_LENGTH); InputStream stream = new ByteArrayInputStream(body, offset, body.length - offset); return new Attachment(h, stream); diff --git a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarManagerImpl.java index 2c720367c..4e8875eec 100644 --- a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarManagerImpl.java @@ -250,7 +250,7 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook, try { BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn, g); - return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue()); + return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID)); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java index 2c55ff4fd..77786f026 100644 --- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java @@ -487,7 +487,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, } private String getPostText(BdfList message) throws FormatException { - MessageType type = MessageType.valueOf(message.getLong(0).intValue()); + MessageType type = MessageType.valueOf(message.getInt(0)); if (type == POST) { // Type, text, signature return message.getString(1); @@ -621,7 +621,6 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, } private MessageType getMessageType(BdfDictionary d) throws FormatException { - Long longType = d.getLong(KEY_TYPE); - return MessageType.valueOf(longType.intValue()); + return MessageType.valueOf(d.getInt(KEY_TYPE)); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java index 4bef7fe85..64ae88196 100644 --- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostFactoryImpl.java @@ -167,6 +167,6 @@ class BlogPostFactoryImpl implements BlogPostFactory { } private MessageType getType(BdfList body) throws FormatException { - return MessageType.valueOf(body.getLong(0).intValue()); + return MessageType.valueOf(body.getInt(0)); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java index d4c135281..b17953892 100644 --- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogPostValidator.java @@ -72,7 +72,7 @@ class BlogPostValidator extends BdfMessageValidator { BdfMessageContext c; - int type = body.getLong(0).intValue(); + int type = body.getInt(0); body.remove(0); switch (MessageType.valueOf(type)) { case POST: diff --git a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java index 1da615926..43a2ef207 100644 --- a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java @@ -114,8 +114,8 @@ class MessageTrackerImpl implements MessageTracker { try { BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g); return new GroupCount( - d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(), - d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(), + d.getInt(GROUP_KEY_MSG_COUNT, 0), + d.getInt(GROUP_KEY_UNREAD_COUNT, 0), d.getLong(GROUP_KEY_LATEST_MSG, 0L) ); } catch (FormatException e) { diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java index 02fa86274..a13c045a7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionValidator.java @@ -47,7 +47,7 @@ class IntroductionValidator extends BdfMessageValidator { @Override protected BdfMessageContext validateMessage(Message m, Group g, BdfList body) throws FormatException { - MessageType type = MessageType.fromValue(body.getLong(0).intValue()); + MessageType type = MessageType.fromValue(body.getInt(0)); switch (type) { case REQUEST: diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java index 5fd50c59c..5d1ae3c28 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/MessageParserImpl.java @@ -59,8 +59,8 @@ class MessageParserImpl implements MessageParser { @Override public MessageMetadata parseMetadata(BdfDictionary d) throws FormatException { - MessageType type = MessageType - .fromValue(d.getLong(MSG_KEY_MESSAGE_TYPE).intValue()); + MessageType type = + MessageType.fromValue(d.getInt(MSG_KEY_MESSAGE_TYPE)); byte[] sessionIdBytes = d.getOptionalRaw(MSG_KEY_SESSION_ID); SessionId sessionId = sessionIdBytes == null ? null : new SessionId(sessionIdBytes); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java index 203ebec57..ccf2da794 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/SessionParserImpl.java @@ -72,7 +72,7 @@ class SessionParserImpl implements SessionParser { @Override public Role getRole(BdfDictionary d) throws FormatException { - return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue()); + return Role.fromValue(d.getInt(SESSION_KEY_ROLE)); } @Override @@ -97,7 +97,7 @@ class SessionParserImpl implements SessionParser { MessageId lastRemoteMessageId = getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID); long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP); - GroupId groupId = getGroupId(d, SESSION_KEY_GROUP_ID); + GroupId groupId = getGroupId(d); Author author = getAuthor(d, SESSION_KEY_AUTHOR); return new Introducee(sessionId, groupId, author, localTimestamp, lastLocalMessageId, lastRemoteMessageId); @@ -126,12 +126,10 @@ class SessionParserImpl implements SessionParser { MessageId lastLocalMessageId = getMessageId(d, SESSION_KEY_LAST_LOCAL_MESSAGE_ID); long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP); - PublicKey ephemeralPublicKey = - getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY); + PublicKey ephemeralPublicKey = getEphemeralPublicKey(d); BdfDictionary tpDict = d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES); - PrivateKey ephemeralPrivateKey = - getEphemeralPrivateKey(d, SESSION_KEY_EPHEMERAL_PRIVATE_KEY); + PrivateKey ephemeralPrivateKey = getEphemeralPrivateKey(d); Map transportProperties = tpDict == null ? null : clientHelper .parseAndValidateTransportPropertiesMap(tpDict); @@ -147,8 +145,7 @@ class SessionParserImpl implements SessionParser { Author remoteAuthor = getAuthor(d, SESSION_KEY_REMOTE_AUTHOR); MessageId lastRemoteMessageId = getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID); - PublicKey ephemeralPublicKey = - getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY); + PublicKey ephemeralPublicKey = getEphemeralPublicKey(d); BdfDictionary tpDict = d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES); Map transportProperties = @@ -162,7 +159,7 @@ class SessionParserImpl implements SessionParser { } private int getState(BdfDictionary d) throws FormatException { - return d.getLong(SESSION_KEY_STATE).intValue(); + return d.getInt(SESSION_KEY_STATE); } private SessionId getSessionId(BdfDictionary d) throws FormatException { @@ -177,9 +174,8 @@ class SessionParserImpl implements SessionParser { return b == null ? null : new MessageId(b); } - private GroupId getGroupId(BdfDictionary d, String key) - throws FormatException { - return new GroupId(d.getRaw(key)); + private GroupId getGroupId(BdfDictionary d) throws FormatException { + return new GroupId(d.getRaw(SESSION_KEY_GROUP_ID)); } private Author getAuthor(BdfDictionary d, String key) @@ -193,23 +189,22 @@ class SessionParserImpl implements SessionParser { if (d == null) return null; Map map = new HashMap<>(d.size()); for (String key : d.keySet()) { - map.put(new TransportId(key), - new KeySetId(d.getLong(key).intValue())); + map.put(new TransportId(key), new KeySetId(d.getInt(key))); } return map; } @Nullable - private PublicKey getEphemeralPublicKey(BdfDictionary d, String key) - throws FormatException { - byte[] keyBytes = d.getOptionalRaw(key); + private PublicKey getEphemeralPublicKey(BdfDictionary d) + throws FormatException { + byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PUBLIC_KEY); return keyBytes == null ? null : new AgreementPublicKey(keyBytes); } @Nullable - private PrivateKey getEphemeralPrivateKey(BdfDictionary d, String key) - throws FormatException { - byte[] keyBytes = d.getOptionalRaw(key); + private PrivateKey getEphemeralPrivateKey(BdfDictionary d) + throws FormatException { + byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PRIVATE_KEY); return keyBytes == null ? null : new AgreementPrivateKey(keyBytes); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java index af0460fd9..1d0a594fe 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java @@ -371,7 +371,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, try { BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn, g); - return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue()); + return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID)); } catch (FormatException e) { throw new DbException(e); } @@ -381,7 +381,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, public ContactId getContactId(GroupId g) throws DbException { try { BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g); - return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue()); + return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID)); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java index 161ea062f..83e8b3036 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/PrivateMessageValidator.java @@ -84,7 +84,7 @@ class PrivateMessageValidator implements MessageValidator { context = validateLegacyPrivateMessage(m, list); } else { // Private message or attachment - int messageType = list.getLong(0).intValue(); + int messageType = list.getInt(0); if (messageType == PRIVATE_MESSAGE) { if (!reader.eof()) throw new FormatException(); context = validatePrivateMessage(m, list); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java index 02abed607..0ca99a1f2 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/GroupMessageValidator.java @@ -63,7 +63,7 @@ class GroupMessageValidator extends BdfMessageValidator { checkSize(body, 4, 6); // Message type (int) - int type = body.getLong(0).intValue(); + int type = body.getInt(0); // Member (author) BdfList memberList = body.getList(1); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java index 3a5ca662a..ff4825c0c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java @@ -530,8 +530,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook BdfList body, BdfDictionary meta) throws DbException, FormatException { - MessageType type = - MessageType.valueOf(meta.getLong(KEY_TYPE).intValue()); + MessageType type = MessageType.valueOf(meta.getInt(KEY_TYPE)); switch (type) { case JOIN: handleJoinMessage(txn, m, meta); @@ -576,8 +575,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook .getMessageMetadataAsDictionary(txn, parentId); if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP)) throw new FormatException(); - MessageType parentType = MessageType - .valueOf(parentMeta.getLong(KEY_TYPE).intValue()); + MessageType parentType = + MessageType.valueOf(parentMeta.getInt(KEY_TYPE)); if (parentType != POST) throw new FormatException(); } @@ -592,8 +591,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook if (!getAuthor(meta).equals(getAuthor(previousMeta))) throw new FormatException(); // previous message must be a POST or JOIN - MessageType previousType = MessageType - .valueOf(previousMeta.getLong(KEY_TYPE).intValue()); + MessageType previousType = + MessageType.valueOf(previousMeta.getInt(KEY_TYPE)); if (previousType != JOIN && previousType != POST) throw new FormatException(); // track message and broadcast event @@ -641,8 +640,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook private Visibility getVisibility(BdfDictionary meta) throws FormatException { - return Visibility - .valueOf(meta.getLong(GROUP_KEY_VISIBILITY).intValue()); + return Visibility.valueOf(meta.getInt(GROUP_KEY_VISIBILITY)); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java index cd78802a5..26742b104 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java @@ -712,9 +712,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl // get all sessions and their states Map sessions = new HashMap<>(); for (BdfDictionary d : metadata.values()) { - if (!sessionParser.isSession(d)) continue; Session session; try { + if (!sessionParser.isSession(d)) continue; session = sessionParser.parseSession(g, d); } catch (FormatException e) { throw new DbException(e); @@ -776,13 +776,12 @@ class GroupInvitationManagerImpl extends ConversationClientImpl // assign protocol messages to their sessions for (Entry entry : metadata.entrySet()) { - // skip all sessions, we are only interested in messages - BdfDictionary d = entry.getValue(); - if (sessionParser.isSession(d)) continue; - // parse message metadata and skip messages not visible in UI MessageMetadata m; try { + // skip all sessions, we are only interested in messages + BdfDictionary d = entry.getValue(); + if (sessionParser.isSession(d)) continue; m = messageParser.parseMetadata(d); } catch (FormatException e) { throw new DbException(e); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java index f04d38fa5..616bfad25 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java @@ -56,7 +56,7 @@ class GroupInvitationValidator extends BdfMessageValidator { @Override protected BdfMessageContext validateMessage(Message m, Group g, BdfList body) throws FormatException { - MessageType type = MessageType.fromValue(body.getLong(0).intValue()); + MessageType type = MessageType.fromValue(body.getInt(0)); switch (type) { case INVITE: return validateInviteMessage(m, body); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java index 244ac6853..33725f426 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java @@ -71,8 +71,8 @@ class MessageParserImpl implements MessageParser { @Override public MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException { - MessageType type = MessageType.fromValue( - meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue()); + MessageType type = + MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE)); GroupId privateGroupId = new GroupId(meta.getRaw(MSG_KEY_PRIVATE_GROUP_ID)); long timestamp = meta.getLong(MSG_KEY_TIMESTAMP); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java index 976c5e3df..f59153888 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParser.java @@ -15,7 +15,7 @@ interface SessionParser { Role getRole(BdfDictionary d) throws FormatException; - boolean isSession(BdfDictionary d); + boolean isSession(BdfDictionary d) throws FormatException; Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException; diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java index a21c80273..4d316ee2e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/SessionParserImpl.java @@ -45,11 +45,11 @@ class SessionParserImpl implements SessionParser { @Override public Role getRole(BdfDictionary d) throws FormatException { - return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue()); + return Role.fromValue(d.getInt(SESSION_KEY_ROLE)); } @Override - public boolean isSession(BdfDictionary d) { + public boolean isSession(BdfDictionary d) throws FormatException { return d.getBoolean(SESSION_KEY_IS_SESSION, false); } @@ -101,7 +101,7 @@ class SessionParserImpl implements SessionParser { } private int getState(BdfDictionary d) throws FormatException { - return d.getLong(SESSION_KEY_STATE).intValue(); + return d.getInt(SESSION_KEY_STATE); } private GroupId getPrivateGroupId(BdfDictionary d) throws FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java index dd8768bcc..124aa4d84 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java @@ -64,8 +64,8 @@ abstract class MessageParserImpl @Override public MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException { - MessageType type = MessageType - .fromValue(meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue()); + MessageType type = + MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE)); GroupId shareableId = new GroupId(meta.getRaw(MSG_KEY_SHAREABLE_ID)); long timestamp = meta.getLong(MSG_KEY_TIMESTAMP); boolean local = meta.getBoolean(MSG_KEY_LOCAL); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java index 7eb84706b..3235a73dc 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParser.java @@ -13,7 +13,7 @@ interface SessionParser { BdfDictionary getAllSessionsQuery(); - boolean isSession(BdfDictionary d); + boolean isSession(BdfDictionary d) throws FormatException; Session parseSession(GroupId contactGroupId, BdfDictionary d) throws FormatException; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java index a29b25e0c..027b65850 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SessionParserImpl.java @@ -40,7 +40,7 @@ class SessionParserImpl implements SessionParser { } @Override - public boolean isSession(BdfDictionary d) { + public boolean isSession(BdfDictionary d) throws FormatException { return d.getBoolean(SESSION_KEY_IS_SESSION, false); } @@ -54,7 +54,7 @@ class SessionParserImpl implements SessionParser { } private int getState(BdfDictionary d) throws FormatException { - return d.getLong(SESSION_KEY_STATE).intValue(); + return d.getInt(SESSION_KEY_STATE); } private GroupId getShareableId(BdfDictionary d) throws FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index b34b9965e..9b74a2b08 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -604,9 +604,9 @@ abstract class SharingManagerImpl // get all sessions and their states Map sessions = new HashMap<>(); for (BdfDictionary d : metadata.values()) { - if (!sessionParser.isSession(d)) continue; Session session; try { + if (!sessionParser.isSession(d)) continue; session = sessionParser.parseSession(contactGroup, d); } catch (FormatException e) { throw new DbException(e); @@ -668,13 +668,12 @@ abstract class SharingManagerImpl // assign protocol messages to their sessions for (Entry entry : metadata.entrySet()) { - // skip all sessions, we are only interested in messages - BdfDictionary d = entry.getValue(); - if (sessionParser.isSession(d)) continue; - // parse message metadata and skip messages not visible in UI MessageMetadata m; try { + // skip all sessions, we are only interested in messages + BdfDictionary d = entry.getValue(); + if (sessionParser.isSession(d)) continue; m = messageParser.parseMetadata(d); } catch (FormatException e) { throw new DbException(e); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java index e03af82d7..cf68fe62d 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java @@ -40,7 +40,7 @@ abstract class SharingValidator extends BdfMessageValidator { @Override protected BdfMessageContext validateMessage(Message m, Group g, BdfList body) throws FormatException { - MessageType type = MessageType.fromValue(body.getLong(0).intValue()); + MessageType type = MessageType.fromValue(body.getInt(0)); switch (type) { case INVITE: return validateInviteMessage(m, body); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java index b8ed89b16..3932d1c99 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java @@ -651,7 +651,7 @@ public class GroupMessageValidatorTest extends ValidatorTestCase { MessageType type, BdfList member, Collection dependencies) throws FormatException { BdfDictionary d = c.getDictionary(); - assertEquals(type.getInt(), d.getLong(KEY_TYPE).intValue()); + assertEquals(type.getInt(), d.getInt(KEY_TYPE).intValue()); assertEquals(message.getTimestamp(), d.getLong(KEY_TIMESTAMP).longValue()); assertFalse(d.getBoolean(KEY_READ)); From 98064e9efe4c7ca533ccc40d518db8b5faa78a41 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Sat, 18 Feb 2023 16:24:21 +0000 Subject: [PATCH 5/9] Remove BdfWriter methods for manually constructing lists and dicts. --- .../bramble/api/data/BdfWriter.java | 8 ------ .../bramble/data/BdfWriterImpl.java | 20 -------------- .../keyagreement/PayloadEncoderImpl.java | 12 +++++---- .../bramble/data/BdfWriterImplTest.java | 27 ------------------- 4 files changed, 7 insertions(+), 60 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java index 8e0e11d73..1427859a6 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfWriter.java @@ -24,13 +24,5 @@ public interface BdfWriter { void writeList(Collection c) throws IOException; - void writeListStart() throws IOException; - - void writeListEnd() throws IOException; - void writeDictionary(Map m) throws IOException; - - void writeDictionaryStart() throws IOException; - - void writeDictionaryEnd() throws IOException; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java index 13812d6c1..263f7bdde 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java @@ -168,16 +168,6 @@ final class BdfWriterImpl implements BdfWriter { else throw new FormatException(); } - @Override - public void writeListStart() throws IOException { - out.write(LIST); - } - - @Override - public void writeListEnd() throws IOException { - out.write(END); - } - @Override public void writeDictionary(Map m) throws IOException { out.write(DICTIONARY); @@ -194,14 +184,4 @@ final class BdfWriterImpl implements BdfWriter { } out.write(END); } - - @Override - public void writeDictionaryStart() throws IOException { - out.write(DICTIONARY); - } - - @Override - public void writeDictionaryEnd() throws IOException { - out.write(END); - } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java index ca90f5f96..86b4109fe 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadEncoderImpl.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.keyagreement; +import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfWriter; import org.briarproject.bramble.api.data.BdfWriterFactory; import org.briarproject.bramble.api.keyagreement.Payload; @@ -32,13 +33,14 @@ class PayloadEncoderImpl implements PayloadEncoder { ByteArrayOutputStream out = new ByteArrayOutputStream(); int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION; out.write(formatIdAndVersion); + BdfList payload = new BdfList(); + payload.add(p.getCommitment()); + for (TransportDescriptor d : p.getTransportDescriptors()) { + payload.add(d.getDescriptor()); + } BdfWriter w = bdfWriterFactory.createWriter(out); try { - w.writeListStart(); // Payload start - w.writeRaw(p.getCommitment()); - for (TransportDescriptor d : p.getTransportDescriptors()) - w.writeList(d.getDescriptor()); - w.writeListEnd(); // Payload end + w.writeList(payload); } catch (IOException e) { // Shouldn't happen with ByteArrayOutputStream throw new AssertionError(e); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java index d643a9b62..6a4e9cdb6 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java @@ -179,33 +179,6 @@ public class BdfWriterImplTest extends BrambleTestCase { "41" + "01" + "33" + "21" + "03" + "80"); } - @Test - public void testWriteDelimitedList() throws IOException { - w.writeListStart(); - w.writeLong(1); - w.writeString("foo"); - w.writeLong(128); - w.writeListEnd(); - // LIST tag, 1 as integer, "foo" as string, 128 as integer, END tag - checkContents("60" + "21" + "01" + - "41" + "03" + "666F6F" + - "22" + "0080" + "80"); - } - - @Test - public void testWriteDelimitedDictionary() throws IOException { - w.writeDictionaryStart(); - w.writeString("foo"); - w.writeLong(123); - w.writeString("bar"); - w.writeNull(); - w.writeDictionaryEnd(); - // DICTIONARY tag, "foo" as string, 123 as integer, "bar" as string, - // NULL tag, END tag - checkContents("70" + "41" + "03" + "666F6F" + - "21" + "7B" + "41" + "03" + "626172" + "00" + "80"); - } - @Test public void testWriteNestedDictionariesAndLists() throws IOException { Map inner = new LinkedHashMap<>(); From 0ced10b3a915ec4163c6cf7a7eb3979bde84112e Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 20 Feb 2023 11:33:48 +0000 Subject: [PATCH 6/9] Use getInt() in a couple more places. --- .../briarproject/bramble/keyagreement/PayloadParserImpl.java | 2 +- .../org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java | 2 +- .../java/org/briarproject/briar/avatar/AvatarValidator.java | 2 +- .../briar/privategroup/PrivateGroupManagerImpl.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java index d41cffa99..6715faf3c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/PayloadParserImpl.java @@ -73,7 +73,7 @@ class PayloadParserImpl implements PayloadParser { List recognised = new ArrayList<>(); for (int i = 1; i < payload.size(); i++) { BdfList descriptor = payload.getList(i); - long transportId = descriptor.getLong(0); + int transportId = descriptor.getInt(0); if (transportId == TRANSPORT_ID_BLUETOOTH) { TransportId id = BluetoothConstants.ID; recognised.add(new TransportDescriptor(id, descriptor)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index 6a890e33c..8c41437e4 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -217,7 +217,7 @@ public class LanTcpPluginTest extends BrambleTestCase { // The plugin should have bound a socket and stored the port number BdfList descriptor = kal.getDescriptor(); assertEquals(3, descriptor.size()); - assertEquals(TRANSPORT_ID_LAN, descriptor.getLong(0).longValue()); + assertEquals(TRANSPORT_ID_LAN, descriptor.getInt(0).intValue()); byte[] address = descriptor.getRaw(1); InetAddress addr = InetAddress.getByAddress(address); assertTrue(addr instanceof Inet4Address); diff --git a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java index 30ec7cb37..1ad955703 100644 --- a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java @@ -76,7 +76,7 @@ class AvatarValidator implements MessageValidator { // 0.0: Message Type, Version, Content-Type checkSize(body, 3); // Message Type - long messageType = body.getLong(0); + long messageType = body.getInt(0); if (messageType != MSG_TYPE_UPDATE) throw new FormatException(); // Version long version = body.getLong(1); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java index ff4825c0c..088cbc4ce 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java @@ -366,7 +366,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook // parse the metadata for (Entry entry : metadata.entrySet()) { BdfDictionary meta = entry.getValue(); - if (meta.getLong(KEY_TYPE) == JOIN.getInt()) { + if (meta.getInt(KEY_TYPE) == JOIN.getInt()) { headers.add(getJoinMessageHeader(txn, g, entry.getKey(), meta, authorInfos)); } else { From ccd6ed9ff01c7225c8ccd04989d54c8e94d35a3b Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 20 Feb 2023 11:56:13 +0000 Subject: [PATCH 7/9] Add fast path for writing BdfDictionaries. --- .../bramble/data/BdfWriterImpl.java | 30 ++++++++++++------- .../bramble/data/BdfWriterImplTest.java | 21 +++++++++++-- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java index 263f7bdde..ca9204923 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfWriterImpl.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.data; import org.briarproject.bramble.api.Bytes; import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfWriter; import org.briarproject.nullsafety.NotNullByDefault; @@ -11,6 +12,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; @@ -171,16 +173,24 @@ final class BdfWriterImpl implements BdfWriter { @Override public void writeDictionary(Map m) throws IOException { out.write(DICTIONARY); - // Write entries in canonical order - List keys = new ArrayList<>(m.size()); - for (Object k : m.keySet()) { - if (!(k instanceof String)) throw new FormatException(); - keys.add((String) k); - } - sort(keys); - for (String key : keys) { - writeString(key); - writeObject(m.get(key)); + if (m instanceof BdfDictionary) { + // Entries are already sorted and keys are known to be strings + for (Entry e : ((BdfDictionary) m).entrySet()) { + writeString(e.getKey()); + writeObject(e.getValue()); + } + } else { + // Check that keys are strings, write entries in canonical order + List keys = new ArrayList<>(m.size()); + for (Object k : m.keySet()) { + if (!(k instanceof String)) throw new FormatException(); + keys.add((String) k); + } + sort(keys); + for (String key : keys) { + writeString(key); + writeObject(m.get(key)); + } } out.write(END); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java index 6a4e9cdb6..0d3af445c 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.data; +import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.util.StringUtils; import org.junit.Test; @@ -168,9 +169,11 @@ public class BdfWriterImplTest extends BrambleTestCase { @Test public void testWriteDictionary() throws IOException { - // Use LinkedHashMap to get predictable iteration order + // Add entries to dictionary in descending order - they should be + // output in ascending order. Use LinkedHashMap to get predictable + // iteration order Map m = new LinkedHashMap<>(); - for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i); + for (int i = 3; i >= 0; i--) m.put(String.valueOf(i), i); w.writeDictionary(m); // DICTIONARY tag, keys as strings and values as integers, END tag checkContents("70" + "41" + "01" + "30" + "21" + "00" + @@ -179,6 +182,20 @@ public class BdfWriterImplTest extends BrambleTestCase { "41" + "01" + "33" + "21" + "03" + "80"); } + @Test + public void testWriteBdfDictionary() throws IOException { + // Add entries to dictionary in descending order - they should be + // output in ascending order + BdfDictionary d = new BdfDictionary(); + for (int i = 3; i >= 0; i--) d.put(String.valueOf(i), i); + w.writeDictionary(d); + // DICTIONARY tag, keys as strings and values as integers, END tag + checkContents("70" + "41" + "01" + "30" + "21" + "00" + + "41" + "01" + "31" + "21" + "01" + + "41" + "01" + "32" + "21" + "02" + + "41" + "01" + "33" + "21" + "03" + "80"); + } + @Test public void testWriteNestedDictionariesAndLists() throws IOException { Map inner = new LinkedHashMap<>(); From 36db5b48eff164547156793a7182708322eb1478 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 20 Feb 2023 13:05:38 +0000 Subject: [PATCH 8/9] Remove methods for manually reading lists and dictionaries. --- .../bramble/api/data/BdfReader.java | 12 ----- .../bramble/data/BdfReaderImpl.java | 50 ++++--------------- .../bramble/data/BdfReaderImplTest.java | 39 --------------- 3 files changed, 9 insertions(+), 92 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java index 7e1ff0e50..fe710becd 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/data/BdfReader.java @@ -60,23 +60,11 @@ public interface BdfReader { BdfList readList() throws IOException; - void readListStart() throws IOException; - - boolean hasListEnd() throws IOException; - - void readListEnd() throws IOException; - void skipList() throws IOException; boolean hasDictionary() throws IOException; BdfDictionary readDictionary() throws IOException; - void readDictionaryStart() throws IOException; - - boolean hasDictionaryEnd() throws IOException; - - void readDictionaryEnd() throws IOException; - void skipDictionary() throws IOException; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java index 72fb8bd21..352c440d1 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/data/BdfReaderImpl.java @@ -365,22 +365,11 @@ final class BdfReaderImpl implements BdfReader { private BdfList readList(int level) throws IOException { if (!hasList()) throw new FormatException(); if (level > nestedLimit) throw new FormatException(); - BdfList list = new BdfList(); - readListStart(); - while (!hasListEnd()) list.add(readObject(level + 1)); - readListEnd(); - return list; - } - - @Override - public void readListStart() throws IOException { - if (!hasList()) throw new FormatException(); hasLookahead = false; - } - - @Override - public boolean hasListEnd() throws IOException { - return hasEnd(); + BdfList list = new BdfList(); + while (!hasEnd()) list.add(readObject(level + 1)); + readEnd(); + return list; } private boolean hasEnd() throws IOException { @@ -389,11 +378,6 @@ final class BdfReaderImpl implements BdfReader { return next == END; } - @Override - public void readListEnd() throws IOException { - readEnd(); - } - private void readEnd() throws IOException { if (!hasEnd()) throw new FormatException(); hasLookahead = false; @@ -403,7 +387,7 @@ final class BdfReaderImpl implements BdfReader { public void skipList() throws IOException { if (!hasList()) throw new FormatException(); hasLookahead = false; - while (!hasListEnd()) skipObject(); + while (!hasEnd()) skipObject(); hasLookahead = false; } @@ -422,10 +406,10 @@ final class BdfReaderImpl implements BdfReader { private BdfDictionary readDictionary(int level) throws IOException { if (!hasDictionary()) throw new FormatException(); if (level > nestedLimit) throw new FormatException(); + hasLookahead = false; BdfDictionary dictionary = new BdfDictionary(); - readDictionaryStart(); String prevKey = null; - while (!hasDictionaryEnd()) { + while (!hasEnd()) { String key = readString(); if (canonical && prevKey != null && key.compareTo(prevKey) <= 0) { // Keys not unique and sorted @@ -434,31 +418,15 @@ final class BdfReaderImpl implements BdfReader { dictionary.put(key, readObject(level + 1)); prevKey = key; } - readDictionaryEnd(); - return dictionary; - } - - @Override - public void readDictionaryStart() throws IOException { - if (!hasDictionary()) throw new FormatException(); - hasLookahead = false; - } - - @Override - public boolean hasDictionaryEnd() throws IOException { - return hasEnd(); - } - - @Override - public void readDictionaryEnd() throws IOException { readEnd(); + return dictionary; } @Override public void skipDictionary() throws IOException { if (!hasDictionary()) throw new FormatException(); hasLookahead = false; - while (!hasDictionaryEnd()) { + while (!hasEnd()) { skipString(); skipObject(); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java index 2b09189b7..f34935cf3 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java @@ -526,25 +526,6 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readList(); } - @Test - public void testReadListManually() throws Exception { - // A list containing 1, "foo", and null - setContents("60" + "21" + "01" + - "41" + "03" + "666F6F" + - "00" + "80"); - r.readListStart(); - assertFalse(r.hasListEnd()); - assertEquals(1, r.readLong()); - assertFalse(r.hasListEnd()); - assertEquals("foo", r.readString()); - assertFalse(r.hasListEnd()); - assertTrue(r.hasNull()); - r.readNull(); - assertTrue(r.hasListEnd()); - r.readListEnd(); - assertTrue(r.eof()); - } - @Test public void testSkipList() throws Exception { // A list containing 1, "foo", and 128 @@ -609,26 +590,6 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readDictionary(); } - @Test - public void testReadDictionaryManually() throws Exception { - // A dictionary containing "foo" -> 123 and "bar" -> null - setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" + - "41" + "03" + "626172" + "00" + "80"); - r.readDictionaryStart(); - assertFalse(r.hasDictionaryEnd()); - assertEquals("foo", r.readString()); - assertFalse(r.hasDictionaryEnd()); - assertEquals(123, r.readLong()); - assertFalse(r.hasDictionaryEnd()); - assertEquals("bar", r.readString()); - assertFalse(r.hasDictionaryEnd()); - assertTrue(r.hasNull()); - r.readNull(); - assertTrue(r.hasDictionaryEnd()); - r.readDictionaryEnd(); - assertTrue(r.eof()); - } - @Test public void testSkipDictionary() throws Exception { // A map containing "foo" -> 123 and "bar" -> null From 1b808584b60ed955824f3cb854d97139c6189cc5 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 20 Feb 2023 13:53:40 +0000 Subject: [PATCH 9/9] Replace some more longs with ints. --- .../briarproject/briar/avatar/AvatarValidator.java | 2 +- .../briar/messaging/MessagingManagerImpl.java | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java index 1ad955703..ce8ed9c0a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/avatar/AvatarValidator.java @@ -76,7 +76,7 @@ class AvatarValidator implements MessageValidator { // 0.0: Message Type, Version, Content-Type checkSize(body, 3); // Message Type - long messageType = body.getInt(0); + int messageType = body.getInt(0); if (messageType != MSG_TYPE_UPDATE) throw new FormatException(); // Version long version = body.getLong(1); diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java index 1d0a594fe..0a6a9c055 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java @@ -182,7 +182,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, try { BdfDictionary metaDict = metadataParser.parse(meta); // Message type is null for version 0.0 private messages - Long messageType = metaDict.getOptionalLong(MSG_KEY_MSG_TYPE); + Integer messageType = metaDict.getOptionalInt(MSG_KEY_MSG_TYPE); if (messageType == null) { incomingPrivateMessage(txn, m, metaDict, true, emptyList()); } else if (messageType == PRIVATE_MESSAGE) { @@ -419,7 +419,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, if (meta == null) continue; try { // Message type is null for version 0.0 private messages - Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE); + Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE); if (messageType != null && messageType != PRIVATE_MESSAGE) continue; long timestamp = meta.getLong(MSG_KEY_TIMESTAMP); @@ -453,7 +453,8 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, Map messages = clientHelper.getMessageMetadataAsDictionary(txn, g); for (Entry entry : messages.entrySet()) { - Long type = entry.getValue().getOptionalLong(MSG_KEY_MSG_TYPE); + Integer type = + entry.getValue().getOptionalInt(MSG_KEY_MSG_TYPE); if (type == null || type == PRIVATE_MESSAGE) result.add(entry.getKey()); } @@ -527,7 +528,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, try { BdfDictionary meta = clientHelper.getMessageMetadataAsDictionary(txn, m); - Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE); + Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE); if (messageType != null && messageType == PRIVATE_MESSAGE) { for (AttachmentHeader h : parseAttachmentHeaders(g, meta)) { try { @@ -554,7 +555,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, int unreadCount = 0; for (Entry entry : metadata.entrySet()) { BdfDictionary meta = entry.getValue(); - Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE); + Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE); if (messageType == null || messageType == PRIVATE_MESSAGE) { msgCount++; if (!meta.getBoolean(MSG_KEY_READ)) unreadCount++;