Index: src/ooxml/java/org/apache/poi/xssf/util/EvilUnclosedBRFixingInputStream.java =================================================================== --- src/ooxml/java/org/apache/poi/xssf/util/EvilUnclosedBRFixingInputStream.java (revision 1054688) +++ src/ooxml/java/org/apache/poi/xssf/util/EvilUnclosedBRFixingInputStream.java (working copy) @@ -59,6 +59,8 @@ System.arraycopy(spare, 0, b, off, spare.length); int ret = spare.length; spare = null; + // Need to do a fixup here + ret = fixUp(b, off, ret); return ret; } @@ -73,11 +75,11 @@ } private int fixUp(byte[] b, int offset, int read) { - // Find places to fix + // Find places to fix, including partials at the end ArrayList fixAt = new ArrayList(); - for(int i=offset; i 0) { + // Buffer is too small so check for a split + int end = b.length - overshoot; + for (int i = fixAt.size()-1; i >= 0; --i) { + int pos = fixAt.get(i); + if (pos > (end - detect.length)) { + // we have a split + overshoot += (pos - (end - detect.length)); + } else if (pos < (end - detect.length)) break; + } + } else { + // Buffer is big enough, but check for a split + int end = b.length; + for (int i = fixAt.size()-1; i >= 0; --i) { + int pos = fixAt.get(i); + if (pos > (end - detect.length)) { + // we have a split + overshoot += (pos - (end - detect.length)); + } else if (pos < (end - detect.length)) break; + } + } + + if (overshoot > 0) { + // We need to take a bit out of the buffer so we have space to + // insert the / into the
tag, or skip a partial
spare = new byte[overshoot]; System.arraycopy(b, b.length-overshoot, spare, 0, overshoot); read -= overshoot; @@ -103,8 +135,9 @@ // positions are valid for(int j=fixAt.size()-1; j>=0; j--) { int i = fixAt.get(j); - - byte[] tmp = new byte[read-i-3]; + int xpos = read - i - 3; + if (xpos < 0) continue; + byte[] tmp = new byte[xpos]; System.arraycopy(b, i+3, tmp, 0, tmp.length); b[i+3] = (byte)'/'; System.arraycopy(tmp, 0, b, i+4, tmp.length); Index: src/ooxml/testcases/org/apache/poi/xssf/util/TestEvilUnclosedBRFixingInputStream.java =================================================================== --- src/ooxml/testcases/org/apache/poi/xssf/util/TestEvilUnclosedBRFixingInputStream.java (revision 1054681) +++ src/ooxml/testcases/org/apache/poi/xssf/util/TestEvilUnclosedBRFixingInputStream.java (working copy) @@ -70,6 +70,39 @@ assertEquals(fixed, result); } + public void testBufferSize() throws Exception { + byte[] orig_root = "

Hello
There!
Tags!

".getBytes("UTF-8"); + byte[] fixed_root = "

Hello
There!
Tags!

".getBytes("UTF-8"); + + ByteArrayOutputStream origStream = new ByteArrayOutputStream(); + ByteArrayOutputStream fixedStream = new ByteArrayOutputStream(); + for (; fixedStream.size() < 2048 + fixed_root.length; ) { + fixedStream.write(fixed_root, 0, fixed_root.length); + origStream.write(orig_root, 0, orig_root.length); + } + byte[] orig = origStream.toByteArray(); + byte[] fixed = fixedStream.toByteArray(); + + EvilUnclosedBRFixingInputStream inp = new EvilUnclosedBRFixingInputStream( + new ByteArrayInputStream(orig) + ); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + boolean going = true; + while(going) { + byte[] b = new byte[1024]; + int r = inp.read(b); + if(r > 0) { + bout.write(b, 0, r); + } else { + going = false; + } + } + + byte[] result = bout.toByteArray(); + assertEquals(fixed, result); + } + protected void assertEquals(byte[] a, byte[] b) { assertEquals(a.length, b.length); for(int i=0; i