From e3df18b1757afca5ffcdc0fcfca20e9ed9e910c4 Mon Sep 17 00:00:00 2001 From: Vishal S Date: Thu, 5 Mar 2026 11:39:08 +0530 Subject: [PATCH 1/5] Add WorkbookEvaluator context-aware fuzz target --- .../poi/fuzz/WorkbookEvaluatorFuzzer.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java new file mode 100644 index 00000000000..dd942b9969e --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java @@ -0,0 +1,122 @@ +/* ==================================================================== + 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 com.code_intelligence.jazzer.api.FuzzedDataProvider; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.formula.EvaluationCell; +import org.apache.poi.ss.formula.FormulaParseException; +import org.apache.poi.ss.formula.WorkbookEvaluator; +import org.apache.poi.ss.formula.eval.NotImplementedException; +import org.apache.poi.ss.usermodel.FormulaError; +import org.apache.poi.util.RecordFormatException; + +/** + * Fuzz target for the Apache POI WorkbookEvaluator engine. + *

+ * This fuzzer exercises the core formula evaluation pipeline by + * setting fuzz-generated formulas on a pre-populated workbook and + * evaluating them through the {@link WorkbookEvaluator}. A 20x20 data + * grid with mixed cell types (numbers, strings, booleans, errors) + * ensures that referential functions (SUM, VLOOKUP, INDEX, etc.) + * reach deep evaluation branches. + *

+ * Used by Google's OSS-Fuzz for continuous security testing. + */ +public class WorkbookEvaluatorFuzzer { + private static HSSFWorkbook workbook; + private static HSSFSheet sheet; + private static HSSFCell fuzzerCell; + private static HSSFEvaluationWorkbook evalWorkbook; + private static EvaluationCell fuzzerEvalCell; + private static WorkbookEvaluator evaluator; + + private static final String[] EXCEL_FUNCTIONS = { + "SUM(", "IF(", "VLOOKUP(", "HLOOKUP(", "INDEX(", "MATCH(", "OFFSET(", "INDIRECT(", + "CHOOSE(", "ADDRESS(", "AREAS(", "CELL(", "COLUMN(", "COLUMNS(", "ROW(", "ROWS(", + "SUMPRODUCT(", "SUMIFS(", "COUNTIFS(", "AVERAGEIFS(", "MAXIFS(", "MINIFS(", + "NPV(", "XIRR(", "PMT(", "FV(", "IRR(", "MIRR(", "NPER(", "RATE(", + "DGET(", "DSUM(", "DAVERAGE(", "DCOUNT(", "DMAX(", "DMIN(", "DPRODUCT(", + "AND(", "OR(", "NOT(", "XOR(", "IFERROR(", "IFNA(", "SWITCH(", + "CONCATENATE(", "TEXTJOIN(", "MID(", "LEFT(", "RIGHT(", "FIND(", "SEARCH(", "SUBSTITUTE(", + "DATE(", "TIME(", "NOW(", "TODAY(", "DATEDIF(", "WORKDAY(", "NETWORKDAYS(" + }; + + public static void fuzzerInitialize() { + workbook = new HSSFWorkbook(); + sheet = workbook.createSheet("FuzzSheet"); + + // Target cell for the fuzzer (A1) + HSSFRow fuzzerRow = sheet.createRow(0); + fuzzerCell = fuzzerRow.createCell(0); + + // Pre-populate a 20x20 grid with mixed data so that referential + // formulas (SUM, MATCH, VLOOKUP, etc.) exercise real evaluation paths. + for (int r = 1; r <= 20; r++) { + HSSFRow row = sheet.createRow(r); + for (int c = 0; c < 20; c++) { + HSSFCell dataCell = row.createCell(c); + switch ((r + c) % 5) { + case 0: dataCell.setCellValue(42.0 * r); break; + case 1: dataCell.setCellValue(-r * 1.5); break; + case 2: dataCell.setCellValue("Data" + c); break; + case 3: dataCell.setCellValue((r % 2 == 0)); break; + case 4: dataCell.setCellErrorValue(FormulaError.VALUE.getCode()); break; + } + } + } + + evalWorkbook = HSSFEvaluationWorkbook.create(workbook); + evaluator = new WorkbookEvaluator(evalWorkbook, null, null); + fuzzerEvalCell = evalWorkbook.getSheet(0).getCell(0, 0); + } + + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + try { + StringBuilder sb = new StringBuilder(); + if (data.consumeBoolean()) { + sb.append(data.pickValue(EXCEL_FUNCTIONS)); + } + sb.append(data.consumeRemainingAsString()); + + String formula = sb.toString(); + if (formula.isEmpty()) { + return; + } + + // 1. Compile: swallow parser exceptions per POI convention + try { + fuzzerCell.setCellFormula(formula); + } catch (Exception e) { + return; + } + + // 2. Evaluate through the core engine + evaluator.evaluate(fuzzerEvalCell); + + } catch (IllegalArgumentException | IllegalStateException | + FormulaParseException | NotImplementedException | + RecordFormatException e) { + // Expected engine/logic limitations on malformed formulas + } + } +} From 801f0384ce69c51c20bbffc46b215a72f4bbe97e Mon Sep 17 00:00:00 2001 From: Vishal S Date: Sun, 8 Mar 2026 14:28:01 +0530 Subject: [PATCH 2/5] Refactor WorkbookEvaluator and FormulaParser fuzzers to remove static state --- .../apache/poi/fuzz/FormulaParserFuzzer.java | 58 +++++++++++++ .../poi/fuzz/WorkbookEvaluatorFuzzer.java | 86 ++++++++----------- 2 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/FormulaParserFuzzer.java diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/FormulaParserFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FormulaParserFuzzer.java new file mode 100644 index 00000000000..b2a91d1836d --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FormulaParserFuzzer.java @@ -0,0 +1,58 @@ +/* ==================================================================== + 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 com.code_intelligence.jazzer.api.FuzzedDataProvider; +import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.formula.FormulaParser; +import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.FormulaParseException; +import org.apache.poi.util.RecordFormatException; + +import java.nio.BufferUnderflowException; +import java.util.NoSuchElementException; + +/** + * Fuzz target for the Apache POI Formula Parser. + */ +public class FormulaParserFuzzer { + + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFEvaluationWorkbook evalWorkbook = HSSFEvaluationWorkbook.create(workbook); + + try { + FormulaType formulaType = data.pickValue(FormulaType.values()); + int sheetIndex = data.consumeInt(-1, 10); + String formula = data.consumeRemainingAsString(); + + if (formula == null || formula.isEmpty()) { + return; + } + + FormulaParser.parse(formula, evalWorkbook, formulaType, sheetIndex); + + } catch (FormulaParseException | IllegalArgumentException | IllegalStateException | + IndexOutOfBoundsException | ArithmeticException | NegativeArraySizeException | + RecordFormatException | BufferUnderflowException | + UnsupportedOperationException | NoSuchElementException e) { + // Expected exceptions on malformed formula syntax + } + } +} diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java index dd942b9969e..f4fdd41dc00 100644 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/WorkbookEvaluatorFuzzer.java @@ -18,40 +18,25 @@ Licensed to the Apache Software Foundation (ASF) under one or more package org.apache.poi.fuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; -import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.EvaluationCell; import org.apache.poi.ss.formula.FormulaParseException; -import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.eval.NotImplementedException; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.util.RecordFormatException; /** * Fuzz target for the Apache POI WorkbookEvaluator engine. - *

- * This fuzzer exercises the core formula evaluation pipeline by - * setting fuzz-generated formulas on a pre-populated workbook and - * evaluating them through the {@link WorkbookEvaluator}. A 20x20 data - * grid with mixed cell types (numbers, strings, booleans, errors) - * ensures that referential functions (SUM, VLOOKUP, INDEX, etc.) - * reach deep evaluation branches. - *

- * Used by Google's OSS-Fuzz for continuous security testing. */ public class WorkbookEvaluatorFuzzer { - private static HSSFWorkbook workbook; - private static HSSFSheet sheet; - private static HSSFCell fuzzerCell; - private static HSSFEvaluationWorkbook evalWorkbook; - private static EvaluationCell fuzzerEvalCell; - private static WorkbookEvaluator evaluator; private static final String[] EXCEL_FUNCTIONS = { - "SUM(", "IF(", "VLOOKUP(", "HLOOKUP(", "INDEX(", "MATCH(", "OFFSET(", "INDIRECT(", + "SUM(", "IF(", "VLOOKUP(", "HLOOKUP(", "INDEX(", "MATCH(", "OFFSET(", "INDIRECT(", "CHOOSE(", "ADDRESS(", "AREAS(", "CELL(", "COLUMN(", "COLUMNS(", "ROW(", "ROWS(", "SUMPRODUCT(", "SUMIFS(", "COUNTIFS(", "AVERAGEIFS(", "MAXIFS(", "MINIFS(", "NPV(", "XIRR(", "PMT(", "FV(", "IRR(", "MIRR(", "NPER(", "RATE(", @@ -61,16 +46,15 @@ public class WorkbookEvaluatorFuzzer { "DATE(", "TIME(", "NOW(", "TODAY(", "DATEDIF(", "WORKDAY(", "NETWORKDAYS(" }; - public static void fuzzerInitialize() { - workbook = new HSSFWorkbook(); - sheet = workbook.createSheet("FuzzSheet"); - - // Target cell for the fuzzer (A1) + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet("FuzzSheet"); + + // Target Cell for the fuzzer (A1) HSSFRow fuzzerRow = sheet.createRow(0); - fuzzerCell = fuzzerRow.createCell(0); + HSSFCell fuzzerCell = fuzzerRow.createCell(0); - // Pre-populate a 20x20 grid with mixed data so that referential - // formulas (SUM, MATCH, VLOOKUP, etc.) exercise real evaluation paths. + // Pre-populate a 20x20 grid with data for referential formulas (SUM, MATCH, etc.) for (int r = 1; r <= 20; r++) { HSSFRow row = sheet.createRow(r); for (int c = 0; c < 20; c++) { @@ -84,39 +68,45 @@ public static void fuzzerInitialize() { } } } + + HSSFEvaluationWorkbook evalWorkbook = HSSFEvaluationWorkbook.create(workbook); + WorkbookEvaluator evaluator = new WorkbookEvaluator(evalWorkbook, null, null); + EvaluationCell fuzzerEvalCell = evalWorkbook.getSheet(0).getCell(0, 0); // Pointer to A1 wrapper - evalWorkbook = HSSFEvaluationWorkbook.create(workbook); - evaluator = new WorkbookEvaluator(evalWorkbook, null, null); - fuzzerEvalCell = evalWorkbook.getSheet(0).getCell(0, 0); - } - - public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { StringBuilder sb = new StringBuilder(); - if (data.consumeBoolean()) { + if (data.consumeBoolean()) { sb.append(data.pickValue(EXCEL_FUNCTIONS)); } sb.append(data.consumeRemainingAsString()); - - String formula = sb.toString(); - if (formula.isEmpty()) { - return; + if (data.consumeBoolean()) { + sb.append(")"); } + + String formula = sb.toString(); + if (formula.isEmpty()) return; - // 1. Compile: swallow parser exceptions per POI convention + // 1. Compile. Swallow Parser RuntimeExceptions per POI security policy. try { fuzzerCell.setCellFormula(formula); } catch (Exception e) { - return; + return; } - - // 2. Evaluate through the core engine + + // 2. Target the evaluation engine directly evaluator.evaluate(fuzzerEvalCell); - - } catch (IllegalArgumentException | IllegalStateException | - FormulaParseException | NotImplementedException | - RecordFormatException e) { - // Expected engine/logic limitations on malformed formulas + + } catch (Exception e) { + // Filter expected engine/logic limitations + if (e instanceof IllegalArgumentException || + e instanceof IllegalStateException || + e instanceof FormulaParseException || + e instanceof NotImplementedException || + e instanceof RecordFormatException) { + return; + } + // FATAL: Evaluation engine crashed internally (NPE, OOB, etc.) + throw new RuntimeException("Found a viable flaw in the EVALUATOR engine!", e); } } } From babc7b0d9dd1a7084ddbae2b5a5843ae1b3c6bd9 Mon Sep 17 00:00:00 2001 From: Vishal S Date: Thu, 12 Mar 2026 13:17:58 +0530 Subject: [PATCH 3/5] Integrate fuzzer for the OOXML Slideshow Rendering engine (PPTX to Image) --- .../java/org/apache/poi/fuzz/POIFuzzer.java | 2 + .../apache/poi/fuzz/POIPPTX2PNGFuzzer.java | 51 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java 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 index f0f4c0b5679..3922b212733 100644 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java @@ -64,6 +64,8 @@ public static void fuzzerTestOneInput(byte[] input) { fuzzAny(input); + POIPPTX2PNGFuzzer.fuzzerTestOneInput(input); + POIHDGFFuzzer.fuzzerTestOneInput(input); POIHMEFFuzzer.fuzzerTestOneInput(input); diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java new file mode 100644 index 00000000000..8b67fa24160 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.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 org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xslf.usermodel.XSLFSlide; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.util.List; + +public class POIPPTX2PNGFuzzer { + public static void fuzzerInitialize() { + POIFuzzer.adjustLimits(); + } + + public static void fuzzerTestOneInput(byte[] input) { + try (XMLSlideShow slideshow = new XMLSlideShow(new ByteArrayInputStream(input))) { + Dimension pgsize = slideshow.getPageSize(); + List slides = slideshow.getSlides(); + for (XSLFSlide slide : slides) { + BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + try { + slide.draw(graphics); + } finally { + graphics.dispose(); + } + } + } catch (Exception | Error e) { + // Expected exceptions on malformed input + } + } +} From ff7c8659d571fa18f9f3edcda92b90d79ee39dcf Mon Sep 17 00:00:00 2001 From: Vishal S Date: Fri, 13 Mar 2026 22:42:20 +0530 Subject: [PATCH 4/5] Consolidate fuzzers: remove individual format fuzzers, keep core targets --- .../org/apache/poi/fuzz/FuzzerRunner.java | 24 ++++++ .../apache/poi/fuzz/POIFileHandlerFuzzer.java | 41 +++++++++-- .../java/org/apache/poi/fuzz/POIFuzzer.java | 34 ++------- .../org/apache/poi/fuzz/POIHDGFFuzzer.java | 50 ------------- .../org/apache/poi/fuzz/POIHMEFFuzzer.java | 48 ------------ .../org/apache/poi/fuzz/POIHPBFFuzzer.java | 54 -------------- .../org/apache/poi/fuzz/POIHPSFFuzzer.java | 60 --------------- .../org/apache/poi/fuzz/POIHSLFFuzzer.java | 73 ------------------- .../org/apache/poi/fuzz/POIHSMFFuzzer.java | 56 -------------- .../org/apache/poi/fuzz/POIHSSFFuzzer.java | 61 ---------------- .../org/apache/poi/fuzz/POIHWPFFuzzer.java | 59 --------------- .../apache/poi/fuzz/POIOldExcelFuzzer.java | 47 ------------ .../apache/poi/fuzz/POIPPTX2PNGFuzzer.java | 51 ------------- .../org/apache/poi/fuzz/POIVisioFuzzer.java | 60 --------------- .../org/apache/poi/fuzz/POIXSLFFuzzer.java | 66 ----------------- .../org/apache/poi/fuzz/POIXSSFFuzzer.java | 62 ---------------- .../org/apache/poi/fuzz/POIXWPFFuzzer.java | 66 ----------------- .../org/apache/poi/fuzz/XLSX2CSVFuzzer.java | 51 ------------- 18 files changed, 63 insertions(+), 900 deletions(-) create mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHDGFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPBFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPSFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSLFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSMFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSSFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHWPFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIOldExcelFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIVisioFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSLFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSSFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXWPFFuzzer.java delete mode 100644 poi-fuzz/src/main/java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java new file mode 100644 index 00000000000..aeaafd4cea9 --- /dev/null +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java @@ -0,0 +1,24 @@ +package org.apache.poi.fuzz; + +import org.apache.poi.fuzz.POIFileHandlerFuzzer; +import java.io.File; +import java.nio.file.Files; + +public class FuzzerRunner { + public static void main(String[] args) throws Exception { + if (args.length == 0) { + System.err.println("Usage: FuzzerRunner "); + System.exit(1); + } + File f = new File(args[0]); + if (!f.exists()) { + System.err.println("File not found: " + args[0]); + System.exit(1); + } + byte[] input = Files.readAllBytes(f.toPath()); + System.out.println("Running fuzzer for file: " + args[0] + " (" + input.length + " bytes)"); + POIFileHandlerFuzzer.fuzzerInitialize(); + POIFileHandlerFuzzer.fuzzerTestOneInput(input); + System.out.println("Success!"); + } +} 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 index 2600d0a0913..ba46bda8138 100644 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFileHandlerFuzzer.java +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFileHandlerFuzzer.java @@ -27,6 +27,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more 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.poifs.filesystem.FileMagic; import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; @@ -68,20 +69,21 @@ Licensed to the Apache Software Foundation (ASF) under one or more * are currently uncovered. */ public class POIFileHandlerFuzzer { - private static final FileHandler[] HANDLERS = new FileHandler[] { + private static final FileHandler[] OLE2_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 HPBFFileHandler(), new OWPFFileHandler(), new POIFSFileHandler(), + new HMEFFileHandler(), + }; + + private static final FileHandler[] OOXML_HANDLERS = new FileHandler[] { + new OPCFileHandler(), new XDGFFileHandler(), new XSLFFileHandler(), new XSSFBFileHandler(), @@ -89,13 +91,38 @@ public class POIFileHandlerFuzzer { new XWPFFileHandler(), }; + private static final FileHandler[] EMF_HANDLERS = new FileHandler[] { + new HEMFFileHandler(), + }; + + private static final FileHandler[] WMF_HANDLERS = new FileHandler[] { + new HWMFFileHandler(), + }; + public static void fuzzerInitialize() { POIFuzzer.adjustLimits(); } public static void fuzzerTestOneInput(byte[] input) throws Exception { ByteArrayInputStream stream = new ByteArrayInputStream(input); - for (FileHandler handler : HANDLERS) { + FileMagic fm = FileMagic.valueOf(stream); + stream.reset(); + + FileHandler[] handlers; + if (fm == FileMagic.OLE2 || fm == FileMagic.UNKNOWN || + fm == FileMagic.BIFF2 || fm == FileMagic.BIFF3 || fm == FileMagic.BIFF4) { + handlers = OLE2_HANDLERS; + } else if (fm == FileMagic.OOXML) { + handlers = OOXML_HANDLERS; + } else if (fm == FileMagic.EMF) { + handlers = EMF_HANDLERS; + } else if (fm == FileMagic.WMF) { + handlers = WMF_HANDLERS; + } else { + return; + } + + for (FileHandler handler : handlers) { stream.mark(input.length); try { 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 index 3922b212733..7cf3a259c6c 100644 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIFuzzer.java @@ -64,35 +64,11 @@ public static void fuzzerTestOneInput(byte[] input) { fuzzAny(input); - POIPPTX2PNGFuzzer.fuzzerTestOneInput(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); + try { + POIFileHandlerFuzzer.fuzzerTestOneInput(input); + } catch (Exception e) { + // expected here + } } public static void fuzzAny(byte[] input) { 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 deleted file mode 100644 index 19070385137..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHDGFFuzzer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* ==================================================================== - 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/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java deleted file mode 100644 index 5e32593f43c..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHMEFFuzzer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* ==================================================================== - 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.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 - } - } -} 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 deleted file mode 100644 index f6ec695fa1d..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPBFFuzzer.java +++ /dev/null @@ -1,54 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 022c5cb3317..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHPSFFuzzer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index a70c36faf9f..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSLFFuzzer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* ==================================================================== - 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 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 deleted file mode 100644 index a2ecc61bf9b..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSMFFuzzer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 2c4552a7bf6..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHSSFFuzzer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index d487c131ac6..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIHWPFFuzzer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 1edeae31ed0..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIOldExcelFuzzer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* ==================================================================== - 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/POIPPTX2PNGFuzzer.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java deleted file mode 100644 index 8b67fa24160..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIPPTX2PNGFuzzer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ==================================================================== - 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 org.apache.poi.xslf.usermodel.XMLSlideShow; -import org.apache.poi.xslf.usermodel.XSLFSlide; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.util.List; - -public class POIPPTX2PNGFuzzer { - public static void fuzzerInitialize() { - POIFuzzer.adjustLimits(); - } - - public static void fuzzerTestOneInput(byte[] input) { - try (XMLSlideShow slideshow = new XMLSlideShow(new ByteArrayInputStream(input))) { - Dimension pgsize = slideshow.getPageSize(); - List slides = slideshow.getSlides(); - for (XSLFSlide slide : slides) { - BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - try { - slide.draw(graphics); - } finally { - graphics.dispose(); - } - } - } catch (Exception | Error e) { - // Expected exceptions on malformed input - } - } -} 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 deleted file mode 100644 index e4db2f80c1f..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIVisioFuzzer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index e95ae96c157..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSLFFuzzer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 4cf7f3de129..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXSSFFuzzer.java +++ /dev/null @@ -1,62 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 74daa9a55a1..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/POIXWPFFuzzer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* ==================================================================== - 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 deleted file mode 100644 index 0cb610544d7..00000000000 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/XLSX2CSVFuzzer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ==================================================================== - 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 From fdd7962ffbf56592f018054325cf2cc96c7efbd9 Mon Sep 17 00:00:00 2001 From: Vishal S Date: Fri, 13 Mar 2026 22:46:02 +0530 Subject: [PATCH 5/5] Consolidate fuzzers: remove individual format fuzzers, keep core targets --- .../java/org/apache/poi/fuzz/FuzzerRunner.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java index aeaafd4cea9..ef9b8c27f35 100644 --- a/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java +++ b/poi-fuzz/src/main/java/org/apache/poi/fuzz/FuzzerRunner.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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 org.apache.poi.fuzz.POIFileHandlerFuzzer;