bug 59830: attach context to any IOException (likely a result of reaching EOF on input stream)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1751986 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2016-07-09 08:05:43 +00:00
parent 518253650a
commit 76dde0aed5

View File

@ -40,6 +40,7 @@ import org.apache.poi.poifs.filesystem.DocumentNode;
import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException; import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.RLEDecompressingInputStream; import org.apache.poi.util.RLEDecompressingInputStream;
@ -179,13 +180,31 @@ public class VBAMacroReader implements Closeable {
private static void trySkip(InputStream in, long n) throws IOException { private static void trySkip(InputStream in, long n) throws IOException {
long skippedBytes = in.skip(n); long skippedBytes = in.skip(n);
if (skippedBytes != n) { if (skippedBytes != n) {
if (skippedBytes < 0) {
throw new IOException( throw new IOException(
"Skipped only " + skippedBytes + " while trying to skip " + n + " bytes. " + "Tried skipping " + n + " bytes, but no bytes were skipped. "
" This should never happen."); + "The end of the stream has been reached or the stream is closed.");
} else {
throw new IOException(
"Tried skipping " + n + " bytes, but only " + skippedBytes + " bytes were skipped. "
+ "This should never happen.");
}
} }
} }
/* // Constants from MS-OVBA: https://msdn.microsoft.com/en-us/library/office/cc313094(v=office.12).aspx
private static final int EOF = -1;
private static final int VERSION_INDEPENDENT_TERMINATOR = 0x0010;
private static final int VERSION_DEPENDENT_TERMINATOR = 0x002B;
private static final int PROJECTVERSION = 0x0009;
private static final int PROJECTCODEPAGE = 0x0003;
private static final int STREAMNAME = 0x001A;
private static final int MODULEOFFSET = 0x0031;
private static final int MODULETYPE_PROCEDURAL = 0x0021;
private static final int MODULETYPE_DOCUMENT_CLASS_OR_DESIGNER = 0x0022;
private static final int PROJECTLCID = 0x0002;
/**
* Reads VBA Project modules from a VBA Project directory located at * Reads VBA Project modules from a VBA Project directory located at
* <tt>macroDir</tt> into <tt>modules</tt>. * <tt>macroDir</tt> into <tt>modules</tt>.
* *
@ -203,24 +222,27 @@ public class VBAMacroReader implements Closeable {
// process DIR // process DIR
RLEDecompressingInputStream in = new RLEDecompressingInputStream(dis); RLEDecompressingInputStream in = new RLEDecompressingInputStream(dis);
String streamName = null; String streamName = null;
int recordId = 0;
try {
while (true) { while (true) {
int id = in.readShort(); recordId = in.readShort();
if (id == -1 || id == 0x0010) { if (EOF == recordId
break; // EOF or TERMINATOR || VERSION_INDEPENDENT_TERMINATOR == recordId) {
break;
} }
int len = in.readInt(); int recordLength = in.readInt();
switch (id) { switch (recordId) {
case 0x0009: // PROJECTVERSION case PROJECTVERSION:
trySkip(in, 6); trySkip(in, 6);
break; break;
case 0x0003: // PROJECTCODEPAGE case PROJECTCODEPAGE:
int codepage = in.readShort(); int codepage = in.readShort();
modules.charset = Charset.forName("Cp" + codepage); modules.charset = Charset.forName("Cp" + codepage);
break; break;
case 0x001A: // STREAMNAME case STREAMNAME:
streamName = readString(in, len, modules.charset); streamName = readString(in, recordLength, modules.charset);
break; break;
case 0x0031: // MODULEOFFSET case MODULEOFFSET:
int moduleOffset = in.readInt(); int moduleOffset = in.readInt();
Module module = modules.get(streamName); Module module = modules.get(streamName);
if (module != null) { if (module != null) {
@ -238,15 +260,18 @@ public class VBAMacroReader implements Closeable {
} }
break; break;
default: default:
try { trySkip(in, recordLength);
trySkip(in, len);
} catch (final IOException e) {
throw new IOException("Error occurred while reading section id " + id, e);
}
break; break;
} }
} }
} catch (final IOException e) {
throw new IOException(
"Error occurred while reading macros at section id "
+ recordId + " (" + HexDump.shortToHex(recordId) + ")", e);
}
finally {
in.close(); in.close();
}
} else if (!startsWithIgnoreCase(name, "__SRP") } else if (!startsWithIgnoreCase(name, "__SRP")
&& !startsWithIgnoreCase(name, "_VBA_PROJECT")) { && !startsWithIgnoreCase(name, "_VBA_PROJECT")) {
// process module, skip __SRP and _VBA_PROJECT since these do not contain macros // process module, skip __SRP and _VBA_PROJECT since these do not contain macros