This is an automated email from the ASF dual-hosted git repository. centic pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/poi.git
commit 90560c33b6f78a4b84e03a9fd8b7feaedb1e49c3 Author: Dominik Stadler <[email protected]> AuthorDate: Sat Mar 7 09:27:07 2026 +0100 Move fuzz-targets from oss-fuzz to Apache POI It's better if we keep the fuzz-targets "near" the sources so we can adjust them along other changes. This will need a change in oss-fuzz to switch to these and remove these fuzz-targets there. --- poi-fuzz/build.gradle | 7 + .../org/apache/poi/fuzz/EncryptDecryptFuzzer.java | 105 ++++++++++++ .../org/apache/poi/fuzz/POIFileHandlerFuzzer.java | 139 +++++++++++++++ .../main/java/org/apache/poi/fuzz/POIFuzzer.java | 190 +++++++++++++++++++++ .../java/org/apache/poi/fuzz/POIHDGFFuzzer.java | 50 ++++++ .../java/org/apache/poi/fuzz/POIHMEFFuzzer.java} | 47 +++-- .../java/org/apache/poi/fuzz/POIHPBFFuzzer.java | 54 ++++++ .../java/org/apache/poi/fuzz/POIHPSFFuzzer.java | 60 +++++++ .../java/org/apache/poi/fuzz/POIHSLFFuzzer.java | 73 ++++++++ .../java/org/apache/poi/fuzz/POIHSMFFuzzer.java | 56 ++++++ .../java/org/apache/poi/fuzz/POIHSSFFuzzer.java | 61 +++++++ .../java/org/apache/poi/fuzz/POIHWPFFuzzer.java | 59 +++++++ .../org/apache/poi/fuzz/POIOldExcelFuzzer.java | 47 +++++ .../java/org/apache/poi/fuzz/POIVisioFuzzer.java | 60 +++++++ .../java/org/apache/poi/fuzz/POIXSLFFuzzer.java | 66 +++++++ .../java/org/apache/poi/fuzz/POIXSSFFuzzer.java | 62 +++++++ .../java/org/apache/poi/fuzz/POIXWPFFuzzer.java | 66 +++++++ .../java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java | 51 ++++++ 18 files changed, 1236 insertions(+), 17 deletions(-) diff --git a/poi-fuzz/build.gradle b/poi-fuzz/build.gradle index 95456641c4..e2ca23203e 100644 --- a/poi-fuzz/build.gradle +++ b/poi-fuzz/build.gradle @@ -21,6 +21,13 @@ dependencies { implementation project(':poi') + implementation project(':poi-scratchpad') + implementation project(':poi-examples') + implementation project(path:':poi-integration', configuration:'tests') + + implementation "org.apache.logging.log4j:log4j-core:${log4jVersion}" + implementation 'org.apache.commons:commons-lang3:3.20.0' + implementation 'org.opentest4j:opentest4j:1.2.0' compileOnly 'com.code-intelligence:jazzer-api:0.22.0' } diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/EncryptDecryptFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/EncryptDecryptFuzzer.java new file mode 100644 index 0000000000..f6f856dff1 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/EncryptDecryptFuzzer.java @@ -0,0 +1,105 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.util.Arrays; + +import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; + +import com.code_intelligence.jazzer.api.FuzzedDataProvider; + +public class EncryptDecryptFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(FuzzedDataProvider data) throws IOException, GeneralSecurityException { + try { + EncryptionMode encryptionMode = EncryptionMode.values()[(data.consumeInt(0, EncryptionMode.values().length - 1))]; + String password = data.consumeString(20); + byte[] testData = data.consumeRemainingAsBytes(); + + EncryptionInfo infoEnc = new EncryptionInfo(encryptionMode); + Encryptor enc = infoEnc.getEncryptor(); + enc.confirmPassword(password); + + byte[] encData; + byte[] encDocument; + try (POIFSFileSystem fsEnc = new POIFSFileSystem()) { + try (OutputStream os = enc.getDataStream(fsEnc)) { + os.write(testData); + } + + UnsynchronizedByteArrayOutputStream bos = UnsynchronizedByteArrayOutputStream.builder().get(); + fsEnc.writeFilesystem(bos); + + bos.close(); + encData = bos.toByteArray(); + + DocumentInputStream dis = fsEnc.getRoot().createDocumentInputStream(DEFAULT_POIFS_ENTRY); + /*long _length =*/ + dis.readLong(); + encDocument = IOUtils.toByteArray(dis); + } + + byte[] actualData; + try (POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(encData))) { + EncryptionInfo infoDec = new EncryptionInfo(fsDec); + Decryptor dec = infoDec.getDecryptor(); + if (!dec.verifyPassword(password)) { + throw new IllegalStateException("Could not verify password when decrypting " + password + "\n" + + HexDump.dump(testData, 0, 0) + " and encrypted \n" + + HexDump.dump(encDocument, 0, 0) + " full encrypted \n" + + HexDump.dump(encData, 0, 0)); + } + InputStream is = dec.getDataStream(fsDec); + + actualData = IOUtils.toByteArray(is); + is.close(); + } + + // input-data and resulting decrypted data should be equal + if (!Arrays.equals(testData, actualData)) { + throw new IllegalStateException("Resulting array was not equal to input-array, " + + "having " + testData.length + " bytes, had actual length " + actualData.length + " and expected \n" + + HexDump.dump(testData, 0, 0) + " and actual \n" + + HexDump.dump(actualData, 0, 0) + " encrypted \n" + + HexDump.dump(encDocument, 0, 0) + " full encrypted \n" + + HexDump.dump(encData, 0, 0)); + } + } catch (IOException | EncryptedDocumentException e) { + // expected, e.g. when something is not supported + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFileHandlerFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFileHandlerFuzzer.java new file mode 100644 index 0000000000..2600d0a091 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFileHandlerFuzzer.java @@ -0,0 +1,139 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.awt.AWTError; +import java.awt.geom.IllegalPathStateException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.ss.formula.FormulaParseException; +import org.apache.poi.ss.formula.eval.NotImplementedException; +import org.apache.poi.stress.FileHandler; +import org.apache.poi.stress.HDGFFileHandler; +import org.apache.poi.stress.HEMFFileHandler; +import org.apache.poi.stress.HMEFFileHandler; +import org.apache.poi.stress.HPBFFileHandler; +import org.apache.poi.stress.HPSFFileHandler; +import org.apache.poi.stress.HSLFFileHandler; +import org.apache.poi.stress.HSMFFileHandler; +import org.apache.poi.stress.HSSFFileHandler; +import org.apache.poi.stress.HWMFFileHandler; +import org.apache.poi.stress.HWPFFileHandler; +import org.apache.poi.stress.OPCFileHandler; +import org.apache.poi.stress.OWPFFileHandler; +import org.apache.poi.stress.POIFSFileHandler; +import org.apache.poi.stress.XDGFFileHandler; +import org.apache.poi.stress.XSLFFileHandler; +import org.apache.poi.stress.XSSFBFileHandler; +import org.apache.poi.stress.XSSFFileHandler; +import org.apache.poi.stress.XWPFFileHandler; +import org.apache.poi.util.DocumentFormatException; +import org.apache.poi.util.RecordFormatException; +import org.apache.poi.xssf.binary.XSSFBParseException; +import org.apache.xmlbeans.XmlException; +import org.opentest4j.AssertionFailedError; +import org.opentest4j.TestAbortedException; +import org.xml.sax.SAXException; + +/** + * A fuzz target which uses the FileHandlers from integration testing of Apache POI + * to execute a number of additional actions after successfully opening documents. + * + * This should extend coverage to some of the getters and other areas of POI which + * are currently uncovered. + */ +public class POIFileHandlerFuzzer { + private static final FileHandler[] HANDLERS = new FileHandler[] { + new HDGFFileHandler(), + new HEMFFileHandler(), + new HMEFFileHandler(), + new HPBFFileHandler(), + new HPSFFileHandler(), + new HSLFFileHandler(), + new HSMFFileHandler(), + new HSSFFileHandler(), + new HWMFFileHandler(), + new HWPFFileHandler(), + new OPCFileHandler(), + new OWPFFileHandler(), + new POIFSFileHandler(), + new XDGFFileHandler(), + new XSLFFileHandler(), + new XSSFBFileHandler(), + new XSSFFileHandler(), + new XWPFFileHandler(), + }; + + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) throws Exception { + ByteArrayInputStream stream = new ByteArrayInputStream(input); + for (FileHandler handler : HANDLERS) { + stream.mark(input.length); + + try { + handler.handleFile(stream, "dummy-file-name"); + } catch (POIXMLException | IOException | SAXException | XmlException | HSLFException | + IllegalArgumentException | IllegalStateException | IndexOutOfBoundsException | NoSuchElementException | + UnsupportedOperationException | NegativeArraySizeException | BufferUnderflowException | + ChunkNotFoundException | RecordInputStream.LeftoverDataException | RecordFormatException | + OpenXML4JException | OpenXML4JRuntimeException | DocumentFormatException | XSSFBParseException | + // some FileHandlers perform checks via assertions, so we expect this type of exception as well + AssertionFailedError | TestAbortedException | + NotImplementedException | FormulaParseException | IllegalPathStateException | ArithmeticException + e) { + // expected here + } catch (AWTError e) { + // POI cannot fix it if there is no DISPLAY + if (!ExceptionUtils.getStackTrace(e).contains("Can't connect to X11 window server")) { + throw e; + } + } catch (NoClassDefFoundError e) { + // POI cannot fix it if there is no DISPLAY + if (!ExceptionUtils.getStackTrace(e).contains("Could not initialize class java.awt.GraphicsEnvironment$LocalGE")) { + throw e; + } + } catch (InternalError e) { + // POI cannot fix it if the font-system is not fully installed, so let's ignore + // this for fuzzing + if (!ExceptionUtils.getStackTrace(e).contains("Fontconfig head is null")) { + throw e; + } + } catch (NullPointerException e) { + // can be removed when commons-compress is > 1.28.0 and changes from COMPRESS-598 are applied + if (!ExceptionUtils.getStackTrace(e).contains("ZipArchiveInputStream.read")) { + throw e; + } + } + + stream.reset(); + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java new file mode 100644 index 0000000000..f0f4c0b567 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java @@ -0,0 +1,190 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.config.AbstractConfiguration; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.extractor.ExtractorFactory; +import org.apache.poi.extractor.POIOLE2TextExtractor; +import org.apache.poi.extractor.POITextExtractor; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hssf.record.RecordFactory; +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.ooxml.extractor.POIXMLPropertiesTextExtractor; +import org.apache.poi.ooxml.extractor.POIXMLTextExtractor; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.util.DocumentFormatException; +import org.apache.poi.util.RecordFormatException; + +/** + * This class provides a simple target for fuzzing Apache POI with Jazzer. + * + * It uses the byte-array to call various method which parse the various + * supported file-formats. + * + * It catches all exceptions that are currently expected. + */ +public class POIFuzzer { + public static void fuzzerInitialize() { + adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + // try to invoke various methods which parse documents/workbooks/slide-shows/... + // all of these catch expected exceptions and thus any failure indicates something + // that we should take a look at + + fuzzAny(input); + + POIHDGFFuzzer.fuzzerTestOneInput(input); + + POIHMEFFuzzer.fuzzerTestOneInput(input); + + POIHPBFFuzzer.fuzzerTestOneInput(input); + + POIHPSFFuzzer.fuzzerTestOneInput(input); + + POIHSLFFuzzer.fuzzerTestOneInput(input); + + POIHSMFFuzzer.fuzzerTestOneInput(input); + + POIHSSFFuzzer.fuzzerTestOneInput(input); + + POIHWPFFuzzer.fuzzerTestOneInput(input); + + POIOldExcelFuzzer.fuzzerTestOneInput(input); + + POIVisioFuzzer.fuzzerTestOneInput(input); + + XLSX2CSVFuzzer.fuzzerTestOneInput(input); + + POIXSLFFuzzer.fuzzerTestOneInput(input); + + POIXSSFFuzzer.fuzzerTestOneInput(input); + + POIXWPFFuzzer.fuzzerTestOneInput(input); + } + + public static void fuzzAny(byte[] input) { + try (Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(input))) { + for (Sheet sheet : wb) { + for (Row row : sheet) { + for (Cell cell : row) { + cell.getAddress(); + cell.getCellType(); + } + } + } + + wb.write(NullOutputStream.INSTANCE); + } catch (IOException | POIXMLException | IllegalArgumentException | RecordFormatException | + IndexOutOfBoundsException | HSLFException | RecordInputStream.LeftoverDataException | + IllegalStateException | BufferUnderflowException | OpenXML4JRuntimeException | + UnsupportedOperationException | NoSuchElementException | NegativeArraySizeException e) { + // expected here + } + + ExtractorFactory.setThreadPrefersEventExtractors(true); + checkExtractor(input); + ExtractorFactory.setAllThreadsPreferEventExtractors(false); + checkExtractor(input); + } + + public static void checkExtractor(byte[] input) { + try (POITextExtractor extractor = ExtractorFactory.createExtractor(new ByteArrayInputStream(input))) { + checkExtractor(extractor); + } catch (IOException | POIXMLException | IllegalArgumentException | RecordFormatException | + IndexOutOfBoundsException | HSLFException | RecordInputStream.LeftoverDataException | + NoSuchElementException | IllegalStateException | ArithmeticException | + BufferUnderflowException | UnsupportedOperationException | DocumentFormatException | + NegativeArraySizeException e) { + // expected here + } + } + + @SuppressWarnings("DuplicatedCode") + public static void checkExtractor(POITextExtractor extractor) throws IOException { + extractor.getDocument(); + extractor.getFilesystem(); + try { + extractor.getMetadataTextExtractor(); + } catch (IllegalStateException e) { + // can happen here + } + try { + extractor.getText(); + } catch (OpenXML4JRuntimeException e) { + // can happen here + } + + if (extractor instanceof POIOLE2TextExtractor) { + POIOLE2TextExtractor ole2Extractor = (POIOLE2TextExtractor) extractor; + ole2Extractor.getRoot(); + ole2Extractor.getSummaryInformation(); + ole2Extractor.getDocSummaryInformation(); + + POITextExtractor[] embedded = ExtractorFactory.getEmbeddedDocsTextExtractors(ole2Extractor); + for (POITextExtractor poiTextExtractor : embedded) { + poiTextExtractor.getText(); + poiTextExtractor.getDocument(); + poiTextExtractor.getFilesystem(); + POITextExtractor metaData = poiTextExtractor.getMetadataTextExtractor(); + metaData.getFilesystem(); + metaData.getText(); + } + } else if (extractor instanceof POIXMLTextExtractor) { + POIXMLTextExtractor xmlExtractor = (POIXMLTextExtractor) extractor; + xmlExtractor.getCoreProperties(); + xmlExtractor.getCustomProperties(); + xmlExtractor.getExtendedProperties(); + POIXMLPropertiesTextExtractor metaData = xmlExtractor.getMetadataTextExtractor(); + metaData.getFilesystem(); + metaData.getText(); + + xmlExtractor.getPackage(); + } + } + + static void adjustLimits() { + // reduce limits so we do not get OOMs with the Xmx settings + // that are used for the fuzzing runs + RecordFactory.setMaxNumberOfRecords(50_000); + EscherRecord.setMaxNumberOfChildren(10_000); + + // remove all appenders to silence log4j output + final var ctx = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false); + final var configuration = (AbstractConfiguration) ctx.getConfiguration(); + final var allAppenders = configuration.getAppenders(); + for (final var appenderName : allAppenders.keySet()) { + configuration.removeAppender(appenderName); + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHDGFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHDGFFuzzer.java new file mode 100644 index 0000000000..1907038513 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHDGFFuzzer.java @@ -0,0 +1,50 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.fuzz.POIFuzzer; +import org.apache.poi.hdgf.HDGFDiagram; +import org.apache.poi.hdgf.extractor.VisioTextExtractor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.RecordFormatException; + +public class POIHDGFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (HDGFDiagram visio = new HDGFDiagram(new POIFSFileSystem(new ByteArrayInputStream(input)))) { + visio.write(NullOutputStream.INSTANCE); + + try (VisioTextExtractor extractor = new VisioTextExtractor(visio)) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | IllegalStateException | RecordFormatException | + IndexOutOfBoundsException | BufferUnderflowException | ArithmeticException | + NoSuchElementException e) { + // expected here + } + } +} diff --git a/poi-fuzz/build.gradle b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java similarity index 51% copy from poi-fuzz/build.gradle copy to poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java index 95456641c4..5e32593f43 100644 --- a/poi-fuzz/build.gradle +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java @@ -15,21 +15,34 @@ limitations under the License. ==================================================================== */ -// Fuzz targets for OSS-Fuzz integration. -// Jazzer is provided at runtime by the OSS-Fuzz build environment; we only -// need the API jar at compile time. - -dependencies { - implementation project(':poi') - - compileOnly 'com.code-intelligence:jazzer-api:0.22.0' +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.poi.fuzz.POIFuzzer; +import org.apache.poi.hmef.HMEFMessage; +import org.apache.poi.util.RecordFormatException; + +public class POIHMEFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try { + HMEFMessage msg = new HMEFMessage(new ByteArrayInputStream(input)); + //noinspection ResultOfMethodCallIgnored + msg.getAttachments(); + msg.getBody(); + //noinspection ResultOfMethodCallIgnored + msg.getMessageAttributes(); + msg.getSubject(); + //noinspection ResultOfMethodCallIgnored + msg.getMessageMAPIAttributes(); + } catch (IOException | IllegalArgumentException | IllegalStateException | RecordFormatException | + ArrayIndexOutOfBoundsException e) { + // expected here + } + } } - -// Fuzz targets are not standard JUnit tests; disable the test task. -test.enabled = false - -javadoc.enabled = false -sourcesJar.enabled = false - -generateMetadataFileForPOIPublication.enabled = false -publishPOIPublicationToMavenLocal.enabled = false diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPBFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPBFFuzzer.java new file mode 100644 index 0000000000..f6ec695fa1 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPBFFuzzer.java @@ -0,0 +1,54 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.hpbf.HPBFDocument; +import org.apache.poi.hpbf.extractor.PublisherTextExtractor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.RecordFormatException; + +public class POIHPBFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (HPBFDocument wb = new HPBFDocument(new ByteArrayInputStream(input))) { + wb.write(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | RecordFormatException | IndexOutOfBoundsException | + BufferUnderflowException | IllegalStateException | NoSuchElementException e) { + // expected here + } + + try { + try (PublisherTextExtractor extractor = new PublisherTextExtractor ( + new POIFSFileSystem(new ByteArrayInputStream(input)).getRoot())) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | RecordFormatException | IndexOutOfBoundsException | + BufferUnderflowException | IllegalStateException | NoSuchElementException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPSFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPSFFuzzer.java new file mode 100644 index 0000000000..022c5cb331 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPSFFuzzer.java @@ -0,0 +1,60 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.fuzz.POIFuzzer; +import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument; +import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.RecordFormatException; + +public class POIHPSFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(input))) { + String workbookName = HSSFWorkbook.getWorkbookDirEntryName(fs.getRoot()); + fs.createDocumentInputStream(workbookName); + + try (HPSFPropertiesOnlyDocument document = new HPSFPropertiesOnlyDocument(fs)) { + document.write(NullOutputStream.INSTANCE); + } + + fs.writeFilesystem(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | IllegalStateException | RecordFormatException | + IndexOutOfBoundsException | BufferUnderflowException | NoSuchElementException e) { + // expected here + } + + try (HPSFPropertiesExtractor extractor = new HPSFPropertiesExtractor(new POIFSFileSystem(new ByteArrayInputStream(input)))) { + POIFuzzer.checkExtractor(extractor); + } catch (IOException | IllegalArgumentException | IllegalStateException | RecordFormatException | + IndexOutOfBoundsException | BufferUnderflowException | NoSuchElementException e) { + // expected + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSLFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSLFFuzzer.java new file mode 100644 index 0000000000..a70c36faf9 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSLFFuzzer.java @@ -0,0 +1,73 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFTextParagraph; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.sl.extractor.SlideShowExtractor; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.RecordFormatException; + +public class POIHSLFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (HSLFSlideShow slides = new HSLFSlideShow(new ByteArrayInputStream(input))) { + slides.write(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | RecordFormatException | + IllegalStateException | HSLFException | IndexOutOfBoundsException | + BufferUnderflowException | POIXMLException | NoSuchElementException | + NegativeArraySizeException e) { + // expected here + } + + try (HSLFSlideShowImpl slides = new HSLFSlideShowImpl(new ByteArrayInputStream(input))) { + slides.write(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | RecordFormatException | + IllegalStateException | HSLFException | IndexOutOfBoundsException | + BufferUnderflowException | POIXMLException | NoSuchElementException | + NegativeArraySizeException e) { + // expected here + } + + try { + try (SlideShowExtractor<HSLFShape, HSLFTextParagraph> extractor = + new SlideShowExtractor<>((HSLFSlideShow) SlideShowFactory.create( + new POIFSFileSystem(new ByteArrayInputStream(input)).getRoot()))) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | RecordFormatException | + IllegalStateException | HSLFException | IndexOutOfBoundsException | + BufferUnderflowException | POIXMLException | NoSuchElementException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSMFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSMFFuzzer.java new file mode 100644 index 0000000000..a2ecc61bf9 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSMFFuzzer.java @@ -0,0 +1,56 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.datatypes.AttachmentChunks; +import org.apache.poi.hsmf.datatypes.DirectoryChunk; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.util.RecordFormatException; + +public class POIHSMFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (MAPIMessage mapi = new MAPIMessage(new ByteArrayInputStream(input))) { + mapi.getAttachmentFiles(); + mapi.getDisplayBCC(); + mapi.getMessageDate(); + + AttachmentChunks[] attachments = mapi.getAttachmentFiles(); + for (AttachmentChunks attachment : attachments) { + DirectoryChunk chunkDirectory = attachment.getAttachmentDirectory(); + if (chunkDirectory != null) { + MAPIMessage attachmentMSG = chunkDirectory.getAsEmbeddedMessage(); + attachmentMSG.getTextBody(); + } + } + } catch (IOException | ChunkNotFoundException | IllegalArgumentException | + RecordFormatException | IndexOutOfBoundsException | NoSuchElementException | + BufferUnderflowException | IllegalStateException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSSFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSSFFuzzer.java new file mode 100644 index 0000000000..2c4552a7bf --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSSFFuzzer.java @@ -0,0 +1,61 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.fuzz.POIFuzzer; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hssf.extractor.ExcelExtractor; +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.RecordFormatException; + +public class POIHSSFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (HSSFWorkbook wb = new HSSFWorkbook(new ByteArrayInputStream(input))) { + wb.write(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | RecordFormatException | IllegalStateException | + IndexOutOfBoundsException | RecordInputStream.LeftoverDataException | + BufferUnderflowException | UnsupportedOperationException | NoSuchElementException | + NegativeArraySizeException e) { + // expected here + } + + try { + try (ExcelExtractor extractor = new ExcelExtractor( + new POIFSFileSystem(new ByteArrayInputStream(input)).getRoot())) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | RecordFormatException | IllegalStateException | + IndexOutOfBoundsException | RecordInputStream.LeftoverDataException | + BufferUnderflowException | UnsupportedOperationException | NoSuchElementException | + NegativeArraySizeException | HSLFException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHWPFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHWPFFuzzer.java new file mode 100644 index 0000000000..d487c131ac --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHWPFFuzzer.java @@ -0,0 +1,59 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.extractor.WordExtractor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.DocumentFormatException; +import org.apache.poi.util.RecordFormatException; + +public class POIHWPFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (HWPFDocument doc = new HWPFDocument(new ByteArrayInputStream(input))) { + doc.write(NullOutputStream.INSTANCE); + } catch (IOException | IllegalArgumentException | IndexOutOfBoundsException | BufferUnderflowException | + NoSuchElementException | RecordFormatException | IllegalStateException | + UnsupportedOperationException | NegativeArraySizeException e) { + // expected here + } + + try { + try (WordExtractor extractor = new WordExtractor( + new POIFSFileSystem(new ByteArrayInputStream(input)).getRoot())) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | IndexOutOfBoundsException | BufferUnderflowException | + NoSuchElementException | RecordFormatException | IllegalStateException | + DocumentFormatException | UnsupportedOperationException | NegativeArraySizeException | + RecordInputStream.LeftoverDataException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIOldExcelFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIOldExcelFuzzer.java new file mode 100644 index 0000000000..1edeae31ed --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIOldExcelFuzzer.java @@ -0,0 +1,47 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.poi.hssf.extractor.OldExcelExtractor; +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.RecordFormatException; + +public class POIOldExcelFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try { + try (OldExcelExtractor extractor = new OldExcelExtractor( + new POIFSFileSystem(new ByteArrayInputStream(input)).getRoot())) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | IllegalArgumentException | RecordFormatException | IndexOutOfBoundsException | + RecordInputStream.LeftoverDataException | IllegalStateException | BufferUnderflowException | + NoSuchElementException e) { + // expected here + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIVisioFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIVisioFuzzer.java new file mode 100644 index 0000000000..e4db2f80c1 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIVisioFuzzer.java @@ -0,0 +1,60 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.poi.hdgf.extractor.VisioTextExtractor; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.util.RecordFormatException; +import org.apache.poi.xdgf.usermodel.XmlVisioDocument; + +public class POIVisioFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (XmlVisioDocument visio = new XmlVisioDocument(new ByteArrayInputStream(input))) { + visio.write(NullOutputStream.INSTANCE); + } catch (IOException | POIXMLException | + BufferUnderflowException | RecordFormatException | OpenXML4JRuntimeException | + IllegalArgumentException | IndexOutOfBoundsException | IllegalStateException e) { + // expected here + } catch (NullPointerException e) { + // can be removed when commons-compress is > 1.28.0 and changes from COMPRESS-598 are applied + if (!ExceptionUtils.getStackTrace(e).contains("ZipArchiveInputStream.read")) { + throw e; + } + } + + try (VisioTextExtractor extractor = new VisioTextExtractor(new ByteArrayInputStream(input))) { + POIFuzzer.checkExtractor(extractor); + } catch (IOException | POIXMLException | IllegalArgumentException | BufferUnderflowException | + RecordFormatException | IndexOutOfBoundsException | ArithmeticException | IllegalStateException | + NoSuchElementException e) { + // expected + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSLFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSLFFuzzer.java new file mode 100644 index 0000000000..e95ae96c15 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSLFFuzzer.java @@ -0,0 +1,66 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.util.RecordFormatException; +import org.apache.poi.xslf.extractor.XSLFExtractor; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xslf.usermodel.XSLFSlideShow; +import org.apache.xmlbeans.XmlException; + +public class POIXSLFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (XMLSlideShow slides = new XMLSlideShow(new ByteArrayInputStream(input))) { + slides.write(NullOutputStream.INSTANCE); + } catch (IOException | POIXMLException | RecordFormatException | OpenXML4JRuntimeException | + IndexOutOfBoundsException | IllegalArgumentException e) { + // expected here + } + + try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(input))) { + try (XSLFSlideShow slides = new XSLFSlideShow(pkg)) { + slides.write(NullOutputStream.INSTANCE); + } + } catch (IOException | OpenXML4JException | XmlException | IllegalArgumentException | POIXMLException | + RecordFormatException | IllegalStateException | OpenXML4JRuntimeException | IndexOutOfBoundsException e) { + // expected here + } + + try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(input))) { + try (XSLFExtractor extractor = new XSLFExtractor(new XMLSlideShow(pkg))) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | InvalidFormatException | POIXMLException | IllegalArgumentException | + RecordFormatException | IllegalStateException | IndexOutOfBoundsException e) { + // expected + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSSFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSSFFuzzer.java new file mode 100644 index 0000000000..4cf7f3de12 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSSFFuzzer.java @@ -0,0 +1,62 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.util.RecordFormatException; +import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.xmlbeans.XmlException; + +public class POIXSSFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (XSSFWorkbook wb = new XSSFWorkbook(new ByteArrayInputStream(input))) { + try (SXSSFWorkbook swb = new SXSSFWorkbook(wb)) { + swb.write(NullOutputStream.INSTANCE); + } + } catch (IOException | POIXMLException | RecordFormatException | IllegalStateException | + OpenXML4JRuntimeException | IllegalArgumentException | IndexOutOfBoundsException e) { + // expected here + } + + try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(input))) { + try (XSSFEventBasedExcelExtractor extractor = new XSSFEventBasedExcelExtractor(pkg)) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | XmlException | OpenXML4JException | POIXMLException | RecordFormatException | + IllegalStateException | IllegalArgumentException | IndexOutOfBoundsException e) { + // expected + } catch (NullPointerException e) { + if (!e.getMessage().startsWith("Cannot invoke \"java.io.InputStream.read(byte[], int, int)\"")) { + throw e; + } + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXWPFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXWPFFuzzer.java new file mode 100644 index 0000000000..74daa9a55a --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXWPFFuzzer.java @@ -0,0 +1,66 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.commons.io.output.NullOutputStream; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.util.RecordFormatException; +import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +public class POIXWPFFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static void fuzzerTestOneInput(byte[] input) { + try (XWPFDocument doc = new XWPFDocument(new ByteArrayInputStream(input))) { + doc.write(NullOutputStream.INSTANCE); + + // if the document can be parsed, trigger some of the getters + try { + doc.getAllEmbeddedParts(); + doc.getAllPictures(); + doc.getAllPackagePictures(); + doc.getPackage(); + doc.getPackagePart(); + doc.getProperties(); + doc.getRelations(); + doc.getCharts(); + doc.getBodyElements(); + doc.getBodyElementsIterator(); + doc.getBodyElementsSpliterator(); + } catch (OpenXML4JException | POIXMLException e) { + // expected + } + + try (XWPFWordExtractor extractor = new XWPFWordExtractor(doc)) { + POIFuzzer.checkExtractor(extractor); + } + } catch (IOException | POIXMLException | RecordFormatException | OpenXML4JRuntimeException | + IllegalArgumentException | IllegalStateException | IndexOutOfBoundsException e) { + // expected + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java new file mode 100644 index 0000000000..0cb610544d --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java @@ -0,0 +1,51 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.fuzz; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.output.NullPrintStream; +import org.apache.poi.fuzz.POIFuzzer; +import org.apache.poi.examples.xssf.eventusermodel.XLSX2CSV; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.util.RecordFormatException; +import org.xml.sax.SAXException; + +public class XLSX2CSVFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (InputStream in = new ByteArrayInputStream(input)) { + OPCPackage p = OPCPackage.open(in); + XLSX2CSV xlsx2csv = new XLSX2CSV(p, NullPrintStream.INSTANCE, 5); + xlsx2csv.process(); + } catch (IOException | OpenXML4JException | SAXException | + POIXMLException | RecordFormatException | + IllegalStateException | IllegalArgumentException | + IndexOutOfBoundsException | OpenXML4JRuntimeException e) { + // expected here + } + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
