mirror of https://github.com/apache/poi.git
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
This commit is contained in:
parent
993bb632f9
commit
5ecbaf5563
|
@ -29,6 +29,7 @@ import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -462,10 +463,18 @@ public class VBAMacroReader implements Closeable {
|
||||||
private static class ASCIIUnicodeStringPair {
|
private static class ASCIIUnicodeStringPair {
|
||||||
private final String ascii;
|
private final String ascii;
|
||||||
private final String unicode;
|
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) {
|
ASCIIUnicodeStringPair(String ascii, String unicode) {
|
||||||
this.ascii = ascii;
|
this.ascii = ascii;
|
||||||
this.unicode = unicode;
|
this.unicode = unicode;
|
||||||
|
pushbackRecordId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getAscii() {
|
private String getAscii() {
|
||||||
|
@ -475,6 +484,10 @@ public class VBAMacroReader implements Closeable {
|
||||||
private String getUnicode() {
|
private String getUnicode() {
|
||||||
return unicode;
|
return unicode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPushbackRecordId() {
|
||||||
|
return pushbackRecordId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processDirStream(Entry dir, ModuleMap modules) throws IOException {
|
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)) {
|
if (dirState.equals(DIR_STATE.INFORMATION_RECORD)) {
|
||||||
dirState = DIR_STATE.REFERENCES_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;
|
break;
|
||||||
case MODULE_DOC_STRING:
|
case MODULE_DOC_STRING:
|
||||||
int modDocStringLength = in.readInt();
|
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();
|
int nameLength = in.readInt();
|
||||||
String ascii = readString(in, nameLength, charset);
|
String ascii = readString(in, nameLength, charset);
|
||||||
int reserved = in.readShort();
|
int reserved = in.readShort();
|
||||||
|
|
||||||
if (reserved != reservedByte) {
|
if (reserved != reservedByte) {
|
||||||
throw new IOException("Expected "+Integer.toHexString(reservedByte)+ "after name before Unicode name, but found: " +
|
if (throwOnUnexpectedReservedByte) {
|
||||||
Integer.toHexString(reserved));
|
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();
|
int unicodeNameRecordLength = in.readInt();
|
||||||
String unicode = readUnicodeString(in, unicodeNameRecordLength);
|
String unicode = readUnicodeString(in, unicodeNameRecordLength);
|
||||||
|
|
|
@ -300,4 +300,21 @@ public class TestVBAMacroReader {
|
||||||
assertEquals(Module.ModuleType.Module, macros.get("M\u00F3dulo1").geModuleType());
|
assertEquals(Module.ModuleType.Module, macros.get("M\u00F3dulo1").geModuleType());
|
||||||
r.close();
|
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<String, Module> macros = r.readMacroModules();
|
||||||
|
assertEquals(20, macros.size());
|
||||||
|
r.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue