From 8e3b60f63d21458c59b9bf10dde10dcc2fa928b0 Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Sat, 30 Dec 2023 11:11:32 +0000 Subject: [PATCH] Bug 66425: Avoid exceptions found via poi-fuzz Prevent StackOverflow via endless nesting Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65303 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1914989 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hslf/dev/BaseTestPPTIterating.java | 1 + .../apache/poi/ddf/EscherContainerRecord.java | 4 +++- .../apache/poi/ddf/UnknownEscherRecord.java | 19 ++++++++++++++++-- ...nimized-POIHSLFFuzzer-5018229722382336.ppt | Bin 0 -> 9157 bytes test-data/spreadsheet/stress.xls | Bin 61952 -> 62464 bytes 5 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5018229722382336.ppt diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java index be18652602..79b200dcca 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/dev/BaseTestPPTIterating.java @@ -70,6 +70,7 @@ public abstract class BaseTestPPTIterating { EXCLUDED.put("clusterfuzz-testcase-minimized-POIFuzzer-6411649193738240.ppt", FileNotFoundException.class); EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4838893004128256.ppt", FileNotFoundException.class); EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-4624961081573376.ppt", FileNotFoundException.class); + EXCLUDED.put("clusterfuzz-testcase-minimized-POIHSLFFuzzer-5018229722382336.ppt", RuntimeException.class); } public static Stream files() { diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java index da4d2a3289..ab30e2c404 100644 --- a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java @@ -91,7 +91,7 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl return fillFields(data, pOffset, recordFactory, 0); } - private int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory, int nesting) { + int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory, int nesting) { if (nesting > MAX_NESTED_CHILD_NODES) { throw new IllegalStateException("Had more than the limit of " + MAX_NESTED_CHILD_NODES + " nested child notes"); } @@ -104,6 +104,8 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl final int childBytesWritten; if (child instanceof EscherContainerRecord) { childBytesWritten = ((EscherContainerRecord)child).fillFields(data, offset, recordFactory, nesting + 1); + } else if (child instanceof UnknownEscherRecord) { + childBytesWritten = ((UnknownEscherRecord)child).fillFields(data, offset, recordFactory, nesting + 1); } else { childBytesWritten = child.fillFields(data, offset, recordFactory); } diff --git a/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java b/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java index c6e71ea099..475cfdecae 100644 --- a/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/UnknownEscherRecord.java @@ -32,13 +32,14 @@ import org.apache.poi.util.LittleEndian; * we do not explicitly support. */ public final class UnknownEscherRecord extends EscherRecord { - //arbitrarily selected; may need to increase private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000_000; private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH; private static final byte[] NO_BYTES = new byte[0]; + private static final int MAX_NESTED_CHILD_NODES = 1000; + /** The data for this record not including the 8 byte header */ private byte[] thedata = NO_BYTES; private final List _childRecords = new ArrayList<>(); @@ -66,6 +67,14 @@ public final class UnknownEscherRecord extends EscherRecord { @Override public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { + return fillFields(data, offset, recordFactory, 0); + } + + int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory, int nesting) { + if (nesting > MAX_NESTED_CHILD_NODES) { + throw new IllegalStateException("Had more than the limit of " + MAX_NESTED_CHILD_NODES + " nested child notes"); + } + int bytesRemaining = readHeader( data, offset ); /* * Have a check between available bytes and bytesRemaining, @@ -83,7 +92,13 @@ public final class UnknownEscherRecord extends EscherRecord { bytesWritten += 8; while ( bytesRemaining > 0 ) { EscherRecord child = recordFactory.createRecord( data, offset ); - int childBytesWritten = child.fillFields( data, offset, recordFactory ); + final int childBytesWritten; + + if (child instanceof EscherContainerRecord) { + childBytesWritten = ((EscherContainerRecord)child).fillFields(data, offset, recordFactory, nesting + 1); + } else { + childBytesWritten = child.fillFields(data, offset, recordFactory); + } bytesWritten += childBytesWritten; offset += childBytesWritten; bytesRemaining -= childBytesWritten; diff --git a/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5018229722382336.ppt b/test-data/slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-5018229722382336.ppt new file mode 100644 index 0000000000000000000000000000000000000000..29c33243bff367cf01a7453109269de096da2afa GIT binary patch literal 9157 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 literal 0 HcmV?d00001 diff --git a/test-data/spreadsheet/stress.xls b/test-data/spreadsheet/stress.xls index 686638aa5314c5470251ba8362866fa8d796b083..43e8f6950df06c0b99b5101fae617ea2a07f706a 100644 GIT binary patch delta 2702 zcmZ9Mdr(wW9LLYu2W|*^cbAMNxHkR6jIL9#$S%uG0}E49Qxg?@q&Q9a#zZuqq*1;~ z@{|!}k!G2eske7TX$5Kcel-e8DT>a(I8MzNGey69_6u~Do&B-rbAG?i_ujLQvMcto zR(nNi{9=Yb4`Yk=4ccVyQ$pb1&d$!R=Mrme{%&9Ax;uBA)f~%mm&|yoxMb%1c?-*# zhXoIb)o~l09ZtrMn+fqb*}TTgA33L&s2*V?q^4yC0^v{~ke(SxPY>Q-TwG!v80U2Q ze5{q-)r+w>GL~mBHoR?c3=Q{NLKa94wg9v+rb17Bn|Z zYMCv{>Kxo77StthudF_EdVO!_s(4DvnCW4RS1l!=pGnio>Hgywb5;3_fFBN8y>I@CrD5io>Tke2ODMI#!B3(s7vT zDslBph?j}JXZ`$nkw?~wM$T`4=*A~t zIZ94WRL&5Yvj@FHFrRu^*FFV%7;G}Jy+VPKh8bmMcd;Y!Z%sGK~R^96eIFkeB=FToxIt0DFk*a)yz%J~{>q>?i- zDrc0;`3AkCFrVF`Yu|!B4mO8a4cKU~$`;-D4s48)GbSo$tjwuJ?^w*=BD4fu4kN zKBtENWk4%Wp9|+GFhh0RS{O0ssI2 delta 2738 zcmZ9Odr*{B7>CbccXivA{kRnk_)Rso<-dwdx>hi`aizTbJy^E+pjoxwL` z^7Weu~Yf&b&KX%$3$#Mi&H78_Qf@@jy-Oiq+L? zwy_Y_(Ft4Z+bw@u7&~l)2dAg;YNH^hYNDYPSS(RdY>?eNkuf{&ERJXFP6uPH=vi(z zCVM=byI^zit+8FUn*wUK5jhh+uK&H8nVGpJkFQ&pg}IF1iU(F2e|KIr8~#HM&b#2R z?n#bbL>c3(7az0Ph&)`xL%a0xtvsMId`FBRZ8>M`U%X2Ik7O$#wVV31UYA?hNdoz=Cjp4X(9|HxrA($1K+H+PL;0_h+M;(+M3!GyEI@XfIE;;Oy zBk)O#pCec}*1-|sxP*@Nb1Xg{?S6zDA(A6Ra)d~ZP~mtK z_6x^BbZj6;nB)kP9AT0pTsStuZM}hW%*43~ih2|IW6;p+emu%2}Cr(g!or;W0c`-1p0VDEGCXTgPYJ1px<CICsJ_oX z%ykxW{W@=iD!-Gz0*!vB_A0GUrS;$aQ?%D8n?{-KwC-)9ELQ4_RXXED=PqL7BsNZA zrwg{3*y+?&e_GdGr)&mgt=RttW$}_TUU3G#a*^y!ViP1bL17aG`xdc@)RlTh*WRYg zMOoz;-MgDIx8!sy&LrV{hu9>EO;Xro!M;muGId?X{ymh&QI8%l5 zePUB3HdSF~33e~Bv#zs7^VwZN+CB=?=m6RMy7vRh(j{rSBFzxe4~fl?*bIf8E!dBU zolRZc{krxsWp`6{1^f3?mMJ+i6=#-k9w0VLVzU%>j$m7eokLxl26WA!>>kSY4(Q%b zD4Q!e=PJ%@;rx`?Y>CZQ*m;8ejM#b9b=P@a`<$|SDf67yyIZf0 z8_MpdtQGserK~`57AVd_;rx!+LWwO@*oA`qp4f%dl{%zrKTuXgS>=%K?VxOt