fix ArrayIndexOutOfBoundsException when decoding a UTF-8 stream

This commit is contained in:
Joel Dice
2012-08-04 16:11:27 -06:00
parent 852d77d0b5
commit c63668c1ce
3 changed files with 134 additions and 11 deletions

View File

@ -13,6 +13,8 @@ package java.io;
import avian.Utf8;
public class InputStreamReader extends Reader {
private static final int MultibytePadding = 4;
private final InputStream in;
public InputStreamReader(InputStream in) {
@ -28,19 +30,60 @@ public class InputStreamReader extends Reader {
throw new UnsupportedEncodingException(encoding);
}
}
public int read(char[] b, int offset, int length) throws IOException {
byte[] buffer = new byte[length];
int c = in.read(buffer);
if (length == 0) {
return 0;
}
if (c <= 0) return c;
byte[] buffer = new byte[length + MultibytePadding];
int bufferLength = length;
int bufferOffset = 0;
while (true) {
int c = in.read(buffer, bufferOffset, bufferLength);
char[] buffer16 = Utf8.decode16(buffer, 0, c);
if (c <= 0) {
if (bufferOffset > 0) {
// if we've reached the end of the stream while trying to
// read a multibyte character, we still need to return any
// competely-decoded characters, plus \ufffd to indicate an
// unknown character
c = 1;
while (bufferOffset > 0) {
char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset);
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
if (buffer16 != null) {
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
c = buffer16.length + 1;
break;
} else {
-- bufferOffset;
}
}
return buffer16.length;
b[offset + c - 1] = '\ufffd';
}
return c;
}
bufferOffset += c;
char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset);
if (buffer16 != null) {
bufferOffset = 0;
System.arraycopy(buffer16, 0, b, offset, buffer16.length);
return buffer16.length;
} else {
// the buffer ended in an incomplete multibyte character, so
// we try to read a another byte at a time until it's complete
bufferLength = 1;
}
}
}
public void close() throws IOException {