bug 62624 -- fix loop identified as dodgy by FindBugs; add a other sanity checks.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1845299 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim Allison 2018-10-31 00:47:51 +00:00
parent 9229cab9bc
commit c257dd71f9
2 changed files with 50 additions and 26 deletions

View File

@ -631,14 +631,19 @@ public class VBAMacroReader implements Closeable {
return new ASCIIUnicodeStringPair(ascii, unicode);
}
private static void readNameMapRecords(InputStream is, Map<String, String> moduleNames, Charset charset) throws IOException {
private static void readNameMapRecords(InputStream is,
Map<String, String> moduleNames, Charset charset) throws IOException {
//see 2.3.3 PROJECTwm Stream: Module Name Information
//multibytecharstring
String mbcs = null;
String unicode = null;
do {
//arbitrary sanity thresholds
final int maxNameRecords = 10000;
final int maxNameLength = 20000;
int records = 0;
while (++records < maxNameRecords) {
try {
mbcs = readMBCS(is, charset);
mbcs = readMBCS(is, charset, maxNameLength);
} catch (EOFException e) {
return;
}
@ -646,53 +651,56 @@ public class VBAMacroReader implements Closeable {
return;
}
try {
unicode = readUnicode(is);
unicode = readUnicode(is, maxNameLength);
} catch (EOFException e) {
return;
}
if (mbcs != null && unicode != null) {
if (unicode != null) {
moduleNames.put(mbcs, unicode);
}
} while (mbcs != null && unicode != null);
}
if (records >= maxNameRecords) {
LOGGER.log(POILogger.WARN, "Hit max name records to read ("+maxNameRecords+"). Stopped early.");
}
}
private static String readUnicode(InputStream is) throws IOException {
private static String readUnicode(InputStream is, int maxNameLength) throws IOException {
//reads null-terminated unicode string
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int b0 = is.read();
int b1 = is.read();
int b0 = IOUtils.readByte(is);
int b1 = IOUtils.readByte(is);
while ((b0 + b1) != 0) {
if (b0 == -1 || b1 == -1) {
throw new EOFException();
}
int read = 2;
while ((b0 + b1) != 0 && read < maxNameLength) {
bos.write(b0);
bos.write(b1);
b0 = is.read();
b1 = is.read();
b0 = IOUtils.readByte(is);
b1 = IOUtils.readByte(is);
read += 2;
}
if (read >= maxNameLength) {
LOGGER.log(POILogger.WARN, "stopped reading unicode name after "+read+" bytes");
}
return new String (bos.toByteArray(), StandardCharsets.UTF_16LE);
}
//returns a string if any bytes are read or null if two 0x00 are read
private static String readMBCS(InputStream is, Charset charset) throws IOException {
private static String readMBCS(InputStream is, Charset charset, int maxLength) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
int b = is.read();
while (b != 0) {
int b = IOUtils.readByte(is);
while (b > 0 && len < maxLength) {
++len;
if (b == -1) {
throw new EOFException();
}
bos.write(b);
b = is.read();
b = IOUtils.readByte(is);
}
//if b was 0 and the above while loop
//was never entered, check for a second 0,
//which would be the sign that you're at the end
//of the list
if (len == 0) {
b = is.read();
if (b == -1) {
throw new EOFException();
}
b = IOUtils.readByte(is);
if (b != 0) {
LOGGER.log(POILogger.WARN, "expected two 0x00 at end of module name map");
}

View File

@ -548,6 +548,22 @@ public final class IOUtils {
return new byte[(int)length];
}
/**
* Simple utility function to check that you haven't hit EOF
* when reading a byte.
*
* @param is inputstream to read
* @return byte read, unless
* @throws IOException on IOException or EOF if -1 is read
*/
public static int readByte(InputStream is) throws IOException {
int b = is.read();
if (b == -1) {
throw new EOFException();
}
return b;
}
private static void throwRFE(long length, int maxLength) {
throw new RecordFormatException("Tried to allocate an array of length "+length +
", but "+ maxLength+" is the maximum for this record type.\n" +