mirror of https://github.com/apache/poi.git
Bug 66425: Avoid NullPointerExceptions and ClassCastExceptions found via poi-fuzz
We try to avoid throwing NullPointerException and ClassCastExceptions, but it was possible to trigger them Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62414 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62442 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62450 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1912365 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4b520ff7c5
commit
9e2ce70d2b
|
@ -21,6 +21,7 @@ import org.apache.xmlbeans.XmlCursor;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -361,7 +362,8 @@ public class XWPFComment implements IBody {
|
||||||
* @return string id
|
* @return string id
|
||||||
*/
|
*/
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return ctComment.getId().toString();
|
final BigInteger id = ctComment.getId();
|
||||||
|
return id == null ? "-1" : id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.apache.poi.hslf.dev;
|
package org.apache.poi.hslf.dev;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -26,7 +27,6 @@ import java.io.Writer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.commons.io.output.StringBuilderWriter;
|
|
||||||
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
|
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
|
||||||
import org.apache.poi.hslf.record.RecordTypes;
|
import org.apache.poi.hslf.record.RecordTypes;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
||||||
|
@ -122,6 +122,11 @@ public final class PPTXMLDump {
|
||||||
int size = (int)LittleEndian.getUInt(data, pos);
|
int size = (int)LittleEndian.getUInt(data, pos);
|
||||||
pos += LittleEndianConsts.INT_SIZE;
|
pos += LittleEndianConsts.INT_SIZE;
|
||||||
|
|
||||||
|
if (size < 0) {
|
||||||
|
// stop processing of invalid header data
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//get name of the record by type
|
//get name of the record by type
|
||||||
String recname = RecordTypes.forTypeID(type).name();
|
String recname = RecordTypes.forTypeID(type).name();
|
||||||
write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding);
|
write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding);
|
||||||
|
@ -214,12 +219,10 @@ public final class PPTXMLDump {
|
||||||
dump.dump(out);
|
dump.dump(out);
|
||||||
out.close();
|
out.close();
|
||||||
} else {
|
} else {
|
||||||
StringBuilderWriter out = new StringBuilderWriter(1024);
|
dump.dump(new BufferedWriter(
|
||||||
dump.dump(out);
|
new OutputStreamWriter(System.out, StandardCharsets.UTF_8)));
|
||||||
System.out.println(out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,6 +194,11 @@ public final class SlideShowDumper {
|
||||||
pos += 8;
|
pos += 8;
|
||||||
out.printf(Locale.ROOT, ind + "That's a %2$s%n", "", recordName);
|
out.printf(Locale.ROOT, ind + "That's a %2$s%n", "", recordName);
|
||||||
|
|
||||||
|
if (len < 0 /*|| len > Integer.MAX_VALUE*/) {
|
||||||
|
// stop processing of invalid header data
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Now check if it's a container or not
|
// Now check if it's a container or not
|
||||||
int container = opt & 0x0f;
|
int container = opt & 0x0f;
|
||||||
|
|
||||||
|
@ -219,7 +224,7 @@ public final class SlideShowDumper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += (int) len;
|
pos += (int) Math.min(len, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,10 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||||
|
import org.apache.poi.poifs.crypt.EncryptionHeader;
|
||||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||||
import org.apache.poi.poifs.crypt.EncryptionMode;
|
import org.apache.poi.poifs.crypt.EncryptionMode;
|
||||||
|
import org.apache.poi.poifs.crypt.EncryptionVerifier;
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
|
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
|
||||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionVerifier;
|
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionVerifier;
|
||||||
|
@ -118,8 +120,16 @@ public final class DocumentEncryptionAtom extends PositionDependentRecordAtom {
|
||||||
bos.writeShort(ei.getVersionMinor());
|
bos.writeShort(ei.getVersionMinor());
|
||||||
bos.writeInt(ei.getEncryptionFlags());
|
bos.writeInt(ei.getEncryptionFlags());
|
||||||
|
|
||||||
((CryptoAPIEncryptionHeader)ei.getHeader()).write(bos);
|
final EncryptionHeader header = ei.getHeader();
|
||||||
((CryptoAPIEncryptionVerifier)ei.getVerifier()).write(bos);
|
if (!(header instanceof CryptoAPIEncryptionHeader)) {
|
||||||
|
throw new IllegalStateException("Had unexpected type of header: " + header.getClass());
|
||||||
|
}
|
||||||
|
((CryptoAPIEncryptionHeader) header).write(bos);
|
||||||
|
final EncryptionVerifier verifier = ei.getVerifier();
|
||||||
|
if (!(verifier instanceof CryptoAPIEncryptionVerifier)) {
|
||||||
|
throw new IllegalStateException("Had unexpected type of verifier: " + verifier.getClass());
|
||||||
|
}
|
||||||
|
((CryptoAPIEncryptionVerifier) verifier).write(bos);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
LittleEndian.putInt(_header, 4, bos.getWriteIndex());
|
LittleEndian.putInt(_header, 4, bos.getWriteIndex());
|
||||||
|
|
|
@ -64,6 +64,7 @@ public abstract class BaseTestPPTIterating {
|
||||||
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6416153805979648.ppt", Exception.class);
|
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6416153805979648.ppt", Exception.class);
|
||||||
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt", RuntimeException.class);
|
EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt", RuntimeException.class);
|
||||||
EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-5429732352851968.ppt", FileNotFoundException.class);
|
EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-5429732352851968.ppt", FileNotFoundException.class);
|
||||||
|
EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-5681320547975168.ppt", FileNotFoundException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Arguments> files() {
|
public static Stream<Arguments> files() {
|
||||||
|
|
|
@ -19,12 +19,20 @@ package org.apache.poi.hslf.dev;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.poi.EmptyFileException;
|
import org.apache.poi.EmptyFileException;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestPPDrawingTextListing extends BaseTestPPTIterating {
|
public class TestPPDrawingTextListing extends BaseTestPPTIterating {
|
||||||
|
static final Set<String> LOCAL_EXCLUDED = new HashSet<>();
|
||||||
|
static {
|
||||||
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIFuzzer-5681320547975168.ppt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMain() throws IOException {
|
void testMain() throws IOException {
|
||||||
// calls System.exit(): PPDrawingTextListing.main(new String[0]);
|
// calls System.exit(): PPDrawingTextListing.main(new String[0]);
|
||||||
|
@ -33,6 +41,17 @@ public class TestPPDrawingTextListing extends BaseTestPPTIterating {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void runOneFile(File pFile) throws Exception {
|
void runOneFile(File pFile) throws Exception {
|
||||||
PPDrawingTextListing.main(new String[]{pFile.getAbsolutePath()});
|
try {
|
||||||
|
PPDrawingTextListing.main(new String[]{pFile.getAbsolutePath()});
|
||||||
|
} catch (IndexOutOfBoundsException | IOException e) {
|
||||||
|
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// work around one file which works here but not in other tests
|
||||||
|
if (pFile.getName().equals("clusterfuzz-testcase-minimized-POIFuzzer-5681320547975168.ppt")) {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ public class TestPPTXMLDump extends BaseTestPPTIterating {
|
||||||
static {
|
static {
|
||||||
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5306877435838464.ppt");
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5306877435838464.ppt");
|
||||||
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6032591399288832.ppt");
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6032591399288832.ppt");
|
||||||
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt");
|
||||||
|
LOCAL_EXCLUDED.add("ppt_with_png_encrypted.ppt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -52,14 +54,18 @@ public class TestPPTXMLDump extends BaseTestPPTIterating {
|
||||||
void runOneFile(File pFile) throws Exception {
|
void runOneFile(File pFile) throws Exception {
|
||||||
try {
|
try {
|
||||||
PPTXMLDump.main(new String[]{pFile.getAbsolutePath()});
|
PPTXMLDump.main(new String[]{pFile.getAbsolutePath()});
|
||||||
|
if (LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
|
throw new IllegalStateException("Expected failure for file " + pFile + ", but processing did not throw an exception");
|
||||||
|
}
|
||||||
} catch (IndexOutOfBoundsException | IOException e) {
|
} catch (IndexOutOfBoundsException | IOException e) {
|
||||||
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// work around one file which works here but not in other tests
|
// work around two files which works here but not in other tests
|
||||||
if (pFile.getName().equals("clusterfuzz-testcase-minimized-POIFuzzer-5429732352851968.ppt")) {
|
if (pFile.getName().equals("clusterfuzz-testcase-minimized-POIFuzzer-5429732352851968.ppt") ||
|
||||||
|
pFile.getName().equals("clusterfuzz-testcase-minimized-POIFuzzer-5681320547975168.ppt")) {
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ public class TestSlideIdListing extends BaseTestPPTIterating {
|
||||||
static final Set<String> LOCAL_EXCLUDED = new HashSet<>();
|
static final Set<String> LOCAL_EXCLUDED = new HashSet<>();
|
||||||
static {
|
static {
|
||||||
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5306877435838464.ppt");
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5306877435838464.ppt");
|
||||||
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -46,7 +47,7 @@ public class TestSlideIdListing extends BaseTestPPTIterating {
|
||||||
void runOneFile(File pFile) throws Exception {
|
void runOneFile(File pFile) throws Exception {
|
||||||
try {
|
try {
|
||||||
SlideIdListing.main(new String[]{pFile.getAbsolutePath()});
|
SlideIdListing.main(new String[]{pFile.getAbsolutePath()});
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (RuntimeException e) {
|
||||||
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class TestSlideShowDumper extends BaseTestPPTIterating {
|
||||||
FAILING.add("cryptoapi-proc2356.ppt");
|
FAILING.add("cryptoapi-proc2356.ppt");
|
||||||
FAILING.add("41384.ppt");
|
FAILING.add("41384.ppt");
|
||||||
FAILING.add("bug56240.ppt");
|
FAILING.add("bug56240.ppt");
|
||||||
|
FAILING.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -66,7 +67,7 @@ public class TestSlideShowDumper extends BaseTestPPTIterating {
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// some old files are not detected correctly
|
// some old files are not detected correctly
|
||||||
if(!OLD_FILES.contains(pFile.getName())) {
|
if(!FAILING.contains(pFile.getName()) && !OLD_FILES.contains(pFile.getName())) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,19 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.poi.EmptyFileException;
|
import org.apache.poi.EmptyFileException;
|
||||||
import org.apache.poi.hslf.HSLFTestDataSamples;
|
import org.apache.poi.hslf.HSLFTestDataSamples;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestSlideShowRecordDumper extends BaseTestPPTIterating {
|
public class TestSlideShowRecordDumper extends BaseTestPPTIterating {
|
||||||
|
static final Set<String> LOCAL_EXCLUDED = new HashSet<>();
|
||||||
|
static {
|
||||||
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMain() throws IOException {
|
void testMain() throws IOException {
|
||||||
SlideShowRecordDumper.main(new String[] {
|
SlideShowRecordDumper.main(new String[] {
|
||||||
|
@ -47,6 +54,12 @@ public class TestSlideShowRecordDumper extends BaseTestPPTIterating {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void runOneFile(File pFile) throws Exception {
|
void runOneFile(File pFile) throws Exception {
|
||||||
SlideShowRecordDumper.main(new String[]{pFile.getAbsolutePath()});
|
try {
|
||||||
|
SlideShowRecordDumper.main(new String[]{pFile.getAbsolutePath()});
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,11 +20,18 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.poi.EmptyFileException;
|
import org.apache.poi.EmptyFileException;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestUserEditAndPersistListing extends BaseTestPPTIterating {
|
public class TestUserEditAndPersistListing extends BaseTestPPTIterating {
|
||||||
|
static final Set<String> LOCAL_EXCLUDED = new HashSet<>();
|
||||||
|
static {
|
||||||
|
LOCAL_EXCLUDED.add("clusterfuzz-testcase-minimized-POIHSLFFuzzer-6360479850954752.ppt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testMain() throws IOException {
|
void testMain() throws IOException {
|
||||||
// calls System.exit(): UserEditAndPersistListing.main(new String[0]);
|
// calls System.exit(): UserEditAndPersistListing.main(new String[0]);
|
||||||
|
@ -33,6 +40,12 @@ public class TestUserEditAndPersistListing extends BaseTestPPTIterating {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void runOneFile(File pFile) throws Exception {
|
void runOneFile(File pFile) throws Exception {
|
||||||
UserEditAndPersistListing.main(new String[]{pFile.getAbsolutePath()});
|
try {
|
||||||
|
UserEditAndPersistListing.main(new String[]{pFile.getAbsolutePath()});
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
if (!LOCAL_EXCLUDED.contains(pFile.getName())) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -61,7 +61,7 @@ public class AgileEncryptionHeader extends EncryptionHeader {
|
||||||
setFlags(0);
|
setFlags(0);
|
||||||
setSizeExtra(0);
|
setSizeExtra(0);
|
||||||
setCspName(null);
|
setCspName(null);
|
||||||
setBlockSize(keyData.getBlockSize());
|
setBlockSize(keyData.getBlockSize() == null ? 0 : keyData.getBlockSize());
|
||||||
|
|
||||||
setChainingMode(keyData.getCipherChaining());
|
setChainingMode(keyData.getCipherChaining());
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue