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); 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 //see 2.3.3 PROJECTwm Stream: Module Name Information
//multibytecharstring //multibytecharstring
String mbcs = null; String mbcs = null;
String unicode = null; String unicode = null;
do { //arbitrary sanity thresholds
final int maxNameRecords = 10000;
final int maxNameLength = 20000;
int records = 0;
while (++records < maxNameRecords) {
try { try {
mbcs = readMBCS(is, charset); mbcs = readMBCS(is, charset, maxNameLength);
} catch (EOFException e) { } catch (EOFException e) {
return; return;
} }
@ -646,53 +651,56 @@ public class VBAMacroReader implements Closeable {
return; return;
} }
try { try {
unicode = readUnicode(is); unicode = readUnicode(is, maxNameLength);
} catch (EOFException e) { } catch (EOFException e) {
return; return;
} }
if (mbcs != null && unicode != null) { if (unicode != null) {
moduleNames.put(mbcs, unicode); 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 //reads null-terminated unicode string
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
int b0 = is.read(); int b0 = IOUtils.readByte(is);
int b1 = is.read(); int b1 = IOUtils.readByte(is);
while ((b0 + b1) != 0) { int read = 2;
if (b0 == -1 || b1 == -1) { while ((b0 + b1) != 0 && read < maxNameLength) {
throw new EOFException();
}
bos.write(b0); bos.write(b0);
bos.write(b1); bos.write(b1);
b0 = is.read(); b0 = IOUtils.readByte(is);
b1 = is.read(); 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); return new String (bos.toByteArray(), StandardCharsets.UTF_16LE);
} }
//returns a string if any bytes are read or null if two 0x00 are read //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(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0; int len = 0;
int b = is.read(); int b = IOUtils.readByte(is);
while (b != 0) { while (b > 0 && len < maxLength) {
++len; ++len;
if (b == -1) {
throw new EOFException();
}
bos.write(b); 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) { if (len == 0) {
b = is.read(); b = IOUtils.readByte(is);
if (b == -1) {
throw new EOFException();
}
if (b != 0) { if (b != 0) {
LOGGER.log(POILogger.WARN, "expected two 0x00 at end of module name map"); 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]; 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) { private static void throwRFE(long length, int maxLength) {
throw new RecordFormatException("Tried to allocate an array of length "+length + throw new RecordFormatException("Tried to allocate an array of length "+length +
", but "+ maxLength+" is the maximum for this record type.\n" + ", but "+ maxLength+" is the maximum for this record type.\n" +