From f6b1435db196b4a2d7079191a15a4018915f70a5 Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Mon, 7 Aug 2023 12:09:31 +0000 Subject: [PATCH] Bug 66425: Avoid a ClassCastException found via oss-fuzz We try to avoid throwing ClassCastException, but it was possible to trigger one here with a specially crafted input-file Should fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61243 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1911507 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/stress/HPSFFileHandler.java | 10 ++----- .../org/apache/poi/hwpf/HWPFDocumentCore.java | 7 ++++- .../converter/TestWordToConverterSuite.java | 21 +++++++++---- .../converter/TestWordToTextConverter.java | 28 +++++++++++++----- ...nimized-POIHWPFFuzzer-5418937293340672.doc | Bin 0 -> 9216 bytes test-data/spreadsheet/stress.xls | Bin 59392 -> 59392 bytes 6 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5418937293340672.doc diff --git a/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java b/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java index fff7daa8ec..705bed2e53 100644 --- a/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java +++ b/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java @@ -43,8 +43,6 @@ import org.apache.poi.util.TempFile; import org.junit.jupiter.api.Test; public class HPSFFileHandler extends POIFSFileHandler { - private static final String NL = System.getProperty("line.separator"); - private static final ThreadLocal copyOutput = ThreadLocal.withInitial(HPSFFileHandler::getTempFile); static final Set EXCLUDES_HANDLE_ADD = StressTestUtils.unmodifiableHashSet( @@ -140,12 +138,10 @@ public class HPSFFileHandler extends POIFSFileHandler { try (InputStream stream = new FileInputStream(path)) { handleFile(stream, path); } - } - // a test-case to test this locally without executing the full TestAllFiles - @Test - void testExtractor() { - File file = new File("test-data/hpsf/TestBug44375.xls"); + File file = new File(path); assertDoesNotThrow(() -> handleExtracting(file)); + + handleAdditional(file); } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java index 5a69dbbb3f..325abc6df8 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java @@ -47,6 +47,7 @@ import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.FileMagic; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.IOUtils; @@ -337,7 +338,11 @@ public abstract class HWPFDocumentCore extends POIDocument { */ protected byte[] getDocumentEntryBytes(String name, int encryptionOffset, final int len) throws IOException { DirectoryNode dir = getDirectory(); - DocumentEntry documentProps = (DocumentEntry)dir.getEntry(name); + final Entry entry = dir.getEntry(name); + if (!(entry instanceof DocumentEntry)) { + throw new IllegalArgumentException("Had unexpected type of entry for name: " + name + ": " + entry); + } + DocumentEntry documentProps = (DocumentEntry) entry; int streamSize = documentProps.getSize(); boolean isEncrypted = (encryptionOffset > -1 && getEncryptionInfo() != null); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java index a809fa7d5e..9f97d63309 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java @@ -23,6 +23,7 @@ import java.io.FilenameFilter; import java.io.StringWriter; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.stream.Stream; import javax.xml.transform.OutputKeys; @@ -52,16 +53,26 @@ public class TestWordToConverterSuite "password_password_cryptoapi.doc", // WORD 2.0 file "word2.doc", - // Corrupt file - "Fuzzed.doc" + // Excel file + "TestRobert_Flaherty.doc", + // Corrupt files + "Fuzzed.doc", + "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5418937293340672.doc", + "TestHPSFWritingFunctionality.doc" ); public static Stream files() { - File directory = POIDataSamples.getDocumentInstance().getFile("../document" ); - FilenameFilter ff = (dir, name) -> name.endsWith(".doc") && !failingFiles.contains(name); + return Stream.concat( + Arrays.stream(getFiles(POIDataSamples.getDocumentInstance().getFile(""))), + Arrays.stream(getFiles(POIDataSamples.getHPSFInstance().getFile(""))) + ).map(Arguments::of); + } + + private static File[] getFiles(File directory) { + FilenameFilter ff = (dir, name) -> name.toLowerCase(Locale.ROOT).endsWith(".doc") && !failingFiles.contains(name); File[] docs = directory.listFiles(ff); assertNotNull(docs); - return Arrays.stream(docs).map(Arguments::of); + return docs; } @ParameterizedTest diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java index 64d89486d0..0d084157c9 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/converter/TestWordToTextConverter.java @@ -25,9 +25,10 @@ import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.InputStream; import java.util.Arrays; +import java.util.List; +import java.util.Locale; import java.util.stream.Stream; -import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.poi.EncryptedDocumentException; @@ -44,6 +45,14 @@ import org.junit.jupiter.params.provider.MethodSource; public class TestWordToTextConverter { private static final Logger LOG = LogManager.getLogger(WordToTextConverter.class); + private static final List failingFiles = Arrays.asList( + // Excel file + "TestRobert_Flaherty.doc", + // Corrupt files + "clusterfuzz-testcase-minimized-POIHWPFFuzzer-5418937293340672.doc", + "TestHPSFWritingFunctionality.doc" + ); + /** * [FAILING] Bug 47731 - Word Extractor considers text copied from some * website as an embedded object @@ -104,13 +113,16 @@ public class TestWordToTextConverter { } public static Stream files() { - String dataDirName = System.getProperty(POIDataSamples.TEST_PROPERTY, - new File("test-data").exists() ? "test-data" : "../test-data"); + return Stream.concat( + Arrays.stream(getFiles(POIDataSamples.getDocumentInstance().getFile(""))), + Arrays.stream(getFiles(POIDataSamples.getHPSFInstance().getFile(""))) + ).map(Arguments::of); + } - File[] documents = new File(dataDirName, "document").listFiles( - (FilenameFilter) new SuffixFileFilter(".doc")); - assertNotNull(documents); - - return Arrays.stream(documents).map(Arguments::of); + private static File[] getFiles(File directory) { + FilenameFilter ff = (dir, name) -> name.toLowerCase(Locale.ROOT).endsWith(".doc") && !failingFiles.contains(name); + File[] docs = directory.listFiles(ff); + assertNotNull(docs); + return docs; } } diff --git a/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5418937293340672.doc b/test-data/document/clusterfuzz-testcase-minimized-POIHWPFFuzzer-5418937293340672.doc new file mode 100644 index 0000000000000000000000000000000000000000..191f096c3f911178f2b017b3951166951198535f GIT binary patch literal 9216 zcmeI1TWnNC7=Zt?JzaJYN?EYn3M^#>J$4IaFBPzmoy~VN8&0KCPBg)idx$J>E2FEn zp-m%}gSPo3@PHR4!(%W7ra}d1e!771AEN4(RK3jtdnL{n5`bImpVy5p;;I`FqMG_{?L| z?KSoWdy8FX@3xzm;&fJ98<6Dzt6qZ3r6XJ>dth65whV^m*vjsZC7oegVjZlA#gt7EBdTSScgpsv}XM*RT9Ftx`eRABSBzR`K zunaG>#ARup^U5rAuSfSyM*l7LMv9+GO=n!VE;BEj7I(nnE9(fmse+p-R2#L^Dp%A0 zgOw^vzk>={V7J(tjU0V8*?tMy4M=RUgGilB8&+T78%C-~Kvq{;md^?hcFQ7rtKCSx zbonm6dAl`|j8I?IwZ_u#$0PHNo$GjRCU=9;)Q6_0jm#-%>N7@O@3D@ACmEX__E@z> zMjgJ^cQN{CYpp@225Q}glyb%vecKj&O`WbkNKnu8TlMof{r1%Tn~!c#4Z7aZE}>yv z_oy?1@m)H=snZBPcCw@&JFCv=xS7}OqnQUJN~8N3G@|khEEXXxys^Czf< zpP@C%KZfA~<+brvFK_5VC4{dZl)k^yE=-?%_1apXoV)1}q(fSscNj6hqd|KuHD~hc zzjP)u&O~UZHH&DM8LDh~^PIN+=vb#eEG?s|>NL6J#%%$gt`hFCbJ{2))?Z*F6|Koo ze!Yho(HP_J$fzCe>e-KO-0bMB{PbOqtXTTh6)pc`&{0&=n?ZY52)xh(ECu8Q=zi~Y z&^_PVp!>e}K}))JE4_x(bzfIB@nZChe}8|Zr*EJy5r2g^UEgUwEw33I*X#uFH9WNJ z^B;bB;YUlu<8{A%Vp;8euU5nNOxgN@*Vbvx_)eyi z{I7!l>N>|M<1O0aXx6)j2;0geORhZVB1`3!EKst*gt9=JS$syt&&k77 zP6Tu*s{iWD3^}1xEh%$9ERb1O+z-(unG?wZ>GOg|`8koSJx*OLJ(Q`)e3NWTM%>>c z!BXhavOpPISPlerZ{@0yg%{tb^U=kk45uWEa{F1q74L>JueeOPTBkzGSACtG{#tI0 zBGi0*I_Q~&^=I}Rl~F3Er@CIt9Cnv;LvafG>yfnH{qABtdz=a=+`Yv)99B*A;5eB{&F{^n{9^0B7_rW|Px&1s7iW*gag?w3 SQlb1+D>z57_1C))NBBR<;kT3k literal 0 HcmV?d00001 diff --git a/test-data/spreadsheet/stress.xls b/test-data/spreadsheet/stress.xls index bfa0cd3f93e22a35db6f739bb84a32f04800f413..97591849fd3a702c78859172afb9d48ed1d6410a 100644 GIT binary patch delta 815 zcmZXRT}V@57{~wTW1BU%vz>Gw(&h>Cs=%Nx>B8nH=tDt@3cax<3(A~JM^qy=gNV++ zf;SL?Lb|M=k5>rFB(h-<)h-4#h!BYggl?*vqUo@qho%|2-#Lkg^5o z-U-<@n;z+HVkhN`;_DLsDbGkXPNlc$Wl4}&`?;+TR$P(T2KQ<^~&P*dBHAH-SfufrTWgu@XB^_r;T`V}ps|3-I91BpYu%XzP}M zPX4PkqzU~z*nL3tQ-(xrAg=Yr5{bc-b|kLF2a>5XJkftmX~>b&sS)7gW#IF5VDvU{ z{2{P*lFjG4_)t3S5pw)%F196DBYJR&+1j>=l*1#94>oys2_V2RR?DTI*G7 z9sgSEFswT&);bL9cl2Y1WZ(sQunoJggZ9PMCaRdQXK74?Uf?{UEHhUhiej9cU3B3P u6i9|K<%LemW@Go~n%S4LKK3f_R@Y4dduM>@w}A6Ku)oCT^Wo6VPx4=z;lA?# delta 533 zcmZp;z}#?wc|#5hE5r03pX4SNva~Z@yRrEf%W-B7-btV2PTpi>p1iTfd=uvc=E>`L zIwptk{+Qgy!!g;0S7P!69+}NPeDl~R2Z>A6^D;0neEqM$z_10#00EX&3J(}W82Erp zu=o{*03cJIf#CpHoF7$O3??ps5LaMeXpq1V{{mD11`u2tp(n7^Vmc zPUoJ^&A_rAY_Skb{0c(?kSPVTKzQa5d#;4YejNuK}lwQUU4gf0K?YZlNVTovHCMJF!*f# zZ6T|`7_wP1GE``DYxXRDsZOAd_(leXF*I)fO)G@xM%7@`=g7(5tUfHVZ!F$pnjVJn{OdCY*j9pn@S zMuv8V_Q^{hYfN5qOhw3KF9So!F$RV+=NK47t}`&i+?Z@x9kAKx_&J%$3ANuBJz)U= DGrX3*