mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 21:59:54 +01:00
Merge branch '1433-illegal-characters' into 'master'
Handle illegal byte sequences safely in BdfReaderImpl Closes #1433 See merge request briar/briar!967
This commit is contained in:
@@ -47,7 +47,7 @@ public class StringUtils {
|
|||||||
try {
|
try {
|
||||||
return s.getBytes("UTF-8");
|
return s.getBytes("UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public class StringUtils {
|
|||||||
try {
|
try {
|
||||||
return decoder.decode(buffer).toString();
|
return decoder.decode(buffer).toString();
|
||||||
} catch (CharacterCodingException e) {
|
} catch (CharacterCodingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,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_32;
|
||||||
import static org.briarproject.bramble.data.Types.STRING_8;
|
import static org.briarproject.bramble.data.Types.STRING_8;
|
||||||
import static org.briarproject.bramble.data.Types.TRUE;
|
import static org.briarproject.bramble.data.Types.TRUE;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -253,7 +254,7 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
||||||
if (length == 0) return "";
|
if (length == 0) return "";
|
||||||
readIntoBuffer(length);
|
readIntoBuffer(length);
|
||||||
return new String(buf, 0, length, "UTF-8");
|
return fromUtf8(buf, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readStringLength() throws IOException {
|
private int readStringLength() throws IOException {
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package org.briarproject.bramble.data;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
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.test.TestUtils.isOptionalTestEnabled;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
public class BdfReaderImplFuzzingTest extends BrambleTestCase {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
assumeTrue(isOptionalTestEnabled(BdfReaderImplFuzzingTest.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStringFuzzing() throws Exception {
|
||||||
|
Random random = new Random();
|
||||||
|
byte[] buf = new byte[22];
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(buf);
|
||||||
|
for (int i = 0; i < 100_000_000; i++) {
|
||||||
|
random.nextBytes(buf);
|
||||||
|
buf[0] = 0x41; // String with 1-byte length
|
||||||
|
buf[1] = 0x14; // Length 20 bytes
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@ import org.briarproject.bramble.api.system.Clock;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.CharacterCodingException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
@@ -22,6 +26,7 @@ import javax.annotation.Nullable;
|
|||||||
import jssc.SerialPortEvent;
|
import jssc.SerialPortEvent;
|
||||||
import jssc.SerialPortEventListener;
|
import jssc.SerialPortEventListener;
|
||||||
|
|
||||||
|
import static java.nio.charset.CodingErrorAction.IGNORE;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
@@ -35,6 +40,8 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ModemImpl.class.getName());
|
Logger.getLogger(ModemImpl.class.getName());
|
||||||
|
|
||||||
|
private static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||||
private static final int MAX_LINE_LENGTH = 256;
|
private static final int MAX_LINE_LENGTH = 256;
|
||||||
private static final int[] BAUD_RATES = {
|
private static final int[] BAUD_RATES = {
|
||||||
256000, 128000, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 1200
|
256000, 128000, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 1200
|
||||||
@@ -106,7 +113,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
// Wait for the event thread to receive "OK"
|
// Wait for the event thread to receive "OK"
|
||||||
boolean success = false;
|
boolean success;
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -353,8 +360,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
for (int i = 0; i < b.length; i++) {
|
for (int i = 0; i < b.length; i++) {
|
||||||
line[lineLen] = b[i];
|
line[lineLen] = b[i];
|
||||||
if (b[i] == '\n') {
|
if (b[i] == '\n') {
|
||||||
// FIXME: Use CharsetDecoder to catch invalid ASCII
|
String s = toAscii(line, lineLen).trim();
|
||||||
String s = new String(line, 0, lineLen, "US-ASCII").trim();
|
|
||||||
lineLen = 0;
|
lineLen = 0;
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Modem status: " + s);
|
if (LOG.isLoggable(INFO)) LOG.info("Modem status: " + s);
|
||||||
if (s.startsWith("CONNECT")) {
|
if (s.startsWith("CONNECT")) {
|
||||||
@@ -436,7 +442,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
// Wait for the event thread to receive "CONNECT"
|
// Wait for the event thread to receive "CONNECT"
|
||||||
boolean success = false;
|
boolean success;
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -461,4 +467,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
stateChange.release();
|
stateChange.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String toAscii(byte[] bytes, int len) {
|
||||||
|
CharsetDecoder decoder = US_ASCII.newDecoder();
|
||||||
|
decoder.onMalformedInput(IGNORE);
|
||||||
|
decoder.onUnmappableCharacter(IGNORE);
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, len);
|
||||||
|
try {
|
||||||
|
return decoder.decode(buffer).toString();
|
||||||
|
} catch (CharacterCodingException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user