From 1db334a6fd25da70f11f6ecb992f5740b3b79570 Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Tue, 30 Oct 2018 13:25:20 +0000 Subject: [PATCH] bug 62625 -- add special handling for REFERENCE_NAME record that may only contain an ascii string, against the spec in VBAMacroReader git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1845238 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/poifs/macros/VBAMacroReader.java | 55 ++++++++++++++++-- .../poi/poifs/macros/TestVBAMacroReader.java | 17 ++++++ test-data/spreadsheet/62625.bin | Bin 0 -> 52736 bytes 3 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test-data/spreadsheet/62625.bin diff --git a/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java b/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java index cb6f3b91f..b44e15c87 100644 --- a/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java +++ b/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java @@ -29,6 +29,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PushbackInputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -462,10 +463,18 @@ public class VBAMacroReader implements Closeable { private static class ASCIIUnicodeStringPair { private final String ascii; private final String unicode; + private final int pushbackRecordId; + + ASCIIUnicodeStringPair(String ascii, int pushbackRecordId) { + this.ascii = ascii; + this.unicode = ""; + this.pushbackRecordId = pushbackRecordId; + } ASCIIUnicodeStringPair(String ascii, String unicode) { this.ascii = ascii; this.unicode = unicode; + pushbackRecordId = -1; } private String getAscii() { @@ -475,6 +484,10 @@ public class VBAMacroReader implements Closeable { private String getUnicode() { return unicode; } + + private int getPushbackRecordId() { + return pushbackRecordId; + } } private void processDirStream(Entry dir, ModuleMap modules) throws IOException { @@ -521,7 +534,27 @@ public class VBAMacroReader implements Closeable { if (dirState.equals(DIR_STATE.INFORMATION_RECORD)) { dirState = DIR_STATE.REFERENCES_RECORD; } - readStringPair(in, modules.charset, REFERENCE_NAME_RESERVED); + ASCIIUnicodeStringPair stringPair = readStringPair(in, + modules.charset, REFERENCE_NAME_RESERVED, false); + if (stringPair.getPushbackRecordId() == -1) { + break; + } + //Special handling for when there's only an ascii string and a REFERENCED_REGISTERED + //record that follows. + //See https://github.com/decalage2/oletools/blob/master/oletools/olevba.py#L1516 + //and https://github.com/decalage2/oletools/pull/135 from (@c1fe) + if (stringPair.getPushbackRecordId() != RecordType.REFERENCE_REGISTERED.id) { + throw new IllegalArgumentException("Unexpected reserved character. "+ + "Expected "+Integer.toHexString(REFERENCE_NAME_RESERVED) + + " or "+Integer.toHexString(RecordType.REFERENCE_REGISTERED.id)+ + " not: "+Integer.toHexString(stringPair.getPushbackRecordId())); + } + //fall through! + case REFERENCE_REGISTERED: + //REFERENCE_REGISTERED must come immediately after + //REFERENCE_NAME to allow for fall through in special case of bug 62625 + int recLength = in.readInt(); + trySkip(in, recLength); break; case MODULE_DOC_STRING: int modDocStringLength = in.readInt(); @@ -582,13 +615,27 @@ public class VBAMacroReader implements Closeable { } } - private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in, Charset charset, int reservedByte) throws IOException { + + + private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in, + Charset charset, int reservedByte) throws IOException { + return readStringPair(in, charset, reservedByte, true); + } + + private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in, + Charset charset, int reservedByte, + boolean throwOnUnexpectedReservedByte) throws IOException { int nameLength = in.readInt(); String ascii = readString(in, nameLength, charset); int reserved = in.readShort(); + if (reserved != reservedByte) { - throw new IOException("Expected "+Integer.toHexString(reservedByte)+ "after name before Unicode name, but found: " + - Integer.toHexString(reserved)); + if (throwOnUnexpectedReservedByte) { + throw new IOException("Expected " + Integer.toHexString(reservedByte) + "after name before Unicode name, but found: " + + Integer.toHexString(reserved)); + } else { + return new ASCIIUnicodeStringPair(ascii, reserved); + } } int unicodeNameRecordLength = in.readInt(); String unicode = readUnicodeString(in, unicodeNameRecordLength); diff --git a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java index 673f82e64..c6853f156 100644 --- a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java +++ b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java @@ -300,4 +300,21 @@ public class TestVBAMacroReader { assertEquals(Module.ModuleType.Module, macros.get("M\u00F3dulo1").geModuleType()); r.close(); } + + @Test + public void bug62625() throws IOException { + //macro comes from Common Crawl: 4BZ22N5QG5R2SUU2MNN47PO7VBQLNYIQ + //A REFERENCE_NAME can sometimes only have an ascii string without + //a reserved byte followed by the unicode string. + //See https://github.com/decalage2/oletools/blob/master/oletools/olevba.py#L1516 + //and https://github.com/decalage2/oletools/pull/135 from (@c1fe) + + + File f = POIDataSamples.getSpreadSheetInstance().getFile("62625.bin"); + VBAMacroReader r = new VBAMacroReader(f); + + Map macros = r.readMacroModules(); + assertEquals(20, macros.size()); + r.close(); + } } diff --git a/test-data/spreadsheet/62625.bin b/test-data/spreadsheet/62625.bin new file mode 100644 index 0000000000000000000000000000000000000000..c7523117f71412acfb5960563b0095495dd493fc GIT binary patch literal 52736 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