You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/11/10 23:04:26 UTC
svn commit: r1769226 - in /poi: site/src/documentation/content/xdocs/
trunk/src/java/org/apache/poi/sl/draw/
trunk/src/scratchpad/src/org/apache/poi/hslf/blip/ trunk/test-data/slideshow/
Author: kiwiwings
Date: Thu Nov 10 23:04:25 2016
New Revision: 1769226
URL: http://svn.apache.org/viewvc?rev=1769226&view=rev
Log:
Bug 60345 - Handle corrupt PICT streams
Added:
poi/trunk/test-data/slideshow/bug60345_Jankovic_final_Retreat_2002.ppt (with props)
poi/trunk/test-data/slideshow/bug60345_paperfigures.ppt (with props)
poi/trunk/test-data/slideshow/bug60345_suba.ppt (with props)
Modified:
poi/site/src/documentation/content/xdocs/status.xml
poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1769226&r1=1769225&r2=1769226&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Thu Nov 10 23:04:25 2016
@@ -64,7 +64,8 @@
<summary-item>Examples to encrypt temp files in SXSSF</summary-item>
</summary>
<actions>
- <action dev="PD" type="add" fixes-bug="59273" module="XSLF,OOXML">Unable to create pptx file by potx file using Apache POI</action>
+ <action dev="PD" type="add" fixes-bug="60345" module="HSLF">Handle corrupt PICT streams</action>
+ <action dev="PD" type="fix" fixes-bug="59273" module="XSLF,OOXML">Unable to create pptx file by potx file using Apache POI</action>
<action dev="PD" type="add" fixes-bug="github-42" module="SS Common">Add setFormattingRanges() to interface ConditionalFormatting</action>
<action dev="PD" type="add" fixes-bug="60321" module="SXSSF examples">Examples: encrypt temp files created when unzipping or zipping an SXSSF workbook</action>
<action dev="PD" type="fix" fixes-bug="60337" module="XWPF">Table row isRepeatingHeader and isCantSplit throw NPE</action>
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java?rev=1769226&r1=1769225&r2=1769226&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java Thu Nov 10 23:04:25 2016
@@ -17,6 +17,7 @@
package org.apache.poi.sl.draw;
+import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -62,7 +63,7 @@ public class BitmapImageRenderer impleme
/**
* Read the image data via ImageIO and optionally try to workaround metadata errors.
- * The resulting image is of image image type {@link BufferedImage#TYPE_INT_ARGB}
+ * The resulting image is of image type {@link BufferedImage#TYPE_INT_ARGB}
*
* @param data the data stream
* @param contentType the content type
@@ -72,6 +73,10 @@ public class BitmapImageRenderer impleme
private static BufferedImage readImage(InputStream data, String contentType) throws IOException {
IOException lastException = null;
BufferedImage img = null;
+ if (data.markSupported()) {
+ data.mark(data.available());
+ }
+
// currently don't use FileCacheImageInputStream,
// because of the risk of filling the file handles (see #59166)
ImageInputStream iis = new MemoryCacheImageInputStream(data);
@@ -84,31 +89,93 @@ public class BitmapImageRenderer impleme
ImageReader reader = iter.next();
ImageReadParam param = reader.getDefaultReadParam();
// 0:default mode, 1:fallback mode
- for (int mode=0; img==null && mode<2; mode++) {
- iis.reset();
+ for (int mode=0; img==null && mode<3; mode++) {
+ lastException = null;
+ try {
+ iis.reset();
+ } catch (IOException e) {
+ if (data.markSupported()) {
+ data.reset();
+ data.mark(data.available());
+ iis.close();
+ iis = new MemoryCacheImageInputStream(data);
+ } else {
+ // can't restore the input stream, so we need to stop processing here
+ lastException = e;
+ break;
+ }
+ }
iis.mark();
- if (mode == 1) {
- // fallback mode for invalid image band metadata
- // see http://stackoverflow.com/questions/10416378
- Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);
- while (imageTypes.hasNext()) {
- ImageTypeSpecifier imageTypeSpecifier = imageTypes.next();
- int bufferedImageType = imageTypeSpecifier.getBufferedImageType();
- if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) {
- param.setDestinationType(imageTypeSpecifier);
+ try {
+
+ switch (mode) {
+ case 0:
+ reader.setInput(iis, false, true);
+ img = reader.read(0, param);
+ break;
+ case 1: {
+ // try to load picture in gray scale mode
+ // fallback mode for invalid image band metadata
+ // see http://stackoverflow.com/questions/10416378
+ Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);
+ while (imageTypes.hasNext()) {
+ ImageTypeSpecifier imageTypeSpecifier = imageTypes.next();
+ int bufferedImageType = imageTypeSpecifier.getBufferedImageType();
+ if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) {
+ param.setDestinationType(imageTypeSpecifier);
+ break;
+ }
+ }
+ reader.setInput(iis, false, true);
+ img = reader.read(0, param);
+ break;
+ }
+ case 2: {
+ // try to load truncated pictures by supplying a BufferedImage
+ // and use the processed data up till the point of error
+ reader.setInput(iis, false, true);
+ int height = reader.getHeight(0);
+ int width = reader.getWidth(0);
+
+ Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);
+ if (imageTypes.hasNext()) {
+ ImageTypeSpecifier imageTypeSpecifier = imageTypes.next();
+ img = imageTypeSpecifier.createBufferedImage(width, height);
+ param.setDestination(img);
+ } else {
+ lastException = new IOException("unable to load even a truncated version of the image.");
+ break;
+ }
+
+ try {
+ reader.read(0, param);
+ } finally {
+ if (img.getType() != BufferedImage.TYPE_INT_ARGB) {
+ int y = findTruncatedBlackBox(img, width, height);
+ if (y < height) {
+ BufferedImage argbImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = argbImg.createGraphics();
+ g.clipRect(0, 0, width, y);
+ g.drawImage(img, 0, 0, null);
+ g.dispose();
+ img.flush();
+ img = argbImg;
+ }
+ }
+ }
break;
}
}
- }
- try {
- reader.setInput(iis, false, true);
- img = reader.read(0, param);
} catch (IOException e) {
- lastException = e;
+ if (mode < 2) {
+ lastException = e;
+ }
} catch (RuntimeException e) {
- lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e);
+ if (mode < 2) {
+ lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e);
+ }
}
}
reader.dispose();
@@ -140,6 +207,21 @@ public class BitmapImageRenderer impleme
return img;
}
+ private static int findTruncatedBlackBox(BufferedImage img, int width, int height) {
+ // scan through the image to find the black box after the truncated data
+ int h = height-1;
+ for (; h > 0; h--) {
+ for (int w = width-1; w > 0; w-=width/10) {
+ int p = img.getRGB(w, h);
+ if (p != 0xff000000) {
+ return h+1;
+ }
+ }
+ }
+ return 0;
+ }
+
+
@Override
public BufferedImage getImage() {
return img;
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java?rev=1769226&r1=1769225&r2=1769226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java Thu Nov 10 23:04:25 2016
@@ -116,6 +116,10 @@ public abstract class Metafile extends H
public int getSize(){
return 34;
}
+
+ public int getWmfSize() {
+ return wmfsize;
+ }
}
protected static byte[] compress(byte[] bytes, int offset, int length) throws IOException {
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java?rev=1769226&r1=1769225&r2=1769226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java Thu Nov 10 23:04:25 2016
@@ -25,12 +25,16 @@ import java.io.IOException;
import java.util.zip.InflaterInputStream;
import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
/**
* Represents Macintosh PICT picture data.
*/
public final class PICT extends Metafile {
+ private static POILogger LOG = POILogFactory.getLogger(PICT.class);
+
public static class NativeHeader {
/**
* skip the first 512 bytes - they are MAC specific crap
@@ -122,18 +126,37 @@ public final class PICT extends Metafile
}
private byte[] read(byte[] data, int pos) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(data);
Header header = new Header();
header.read(data, pos);
bis.skip(pos + header.getSize());
- InflaterInputStream inflater = new InflaterInputStream( bis );
byte[] chunk = new byte[4096];
- int count;
- while ((count = inflater.read(chunk)) >=0 ) {
- out.write(chunk,0,count);
+ ByteArrayOutputStream out = new ByteArrayOutputStream(header.getWmfSize());
+ InflaterInputStream inflater = new InflaterInputStream( bis );
+ try {
+ int count;
+ while ((count = inflater.read(chunk)) >=0 ) {
+ out.write(chunk,0,count);
+ // PICT zip-stream can be erroneous, so we clear the array to determine
+ // the maximum of read bytes, after the inflater crashed
+ bytefill(chunk, (byte)0);
+ }
+ } catch (Exception e) {
+ int lastLen;
+ for (lastLen=chunk.length-1; lastLen>=0 && chunk[lastLen] == 0; lastLen--);
+ if (++lastLen > 0) {
+ if (header.getWmfSize() > out.size()) {
+ // sometimes the wmfsize is smaller than the amount of already successfully read bytes
+ // in this case we take the lastLen as-is, otherwise we truncate it to the given size
+ lastLen = Math.min(lastLen, header.getWmfSize() - out.size());
+ }
+ out.write(chunk,0,lastLen);
+ }
+ // End of picture marker for PICT is 0x00 0xFF
+ LOG.log(POILogger.ERROR, "PICT zip-stream is invalid, read as much as possible. Uncompressed length of header: "+header.getWmfSize()+" / Read bytes: "+out.size(), e);
+ } finally {
+ inflater.close();
}
- inflater.close();
return out.toByteArray();
}
@@ -192,4 +215,22 @@ public final class PICT extends Metafile
throw new IllegalArgumentException(signature+" is not a valid instance/signature value for PICT");
}
}
+
+
+ /*
+ * initialize a smaller piece of the array and use the System.arraycopy
+ * call to fill in the rest of the array in an expanding binary fashion
+ */
+ private static void bytefill(byte[] array, byte value) {
+ // http://stackoverflow.com/questions/9128737/fastest-way-to-set-all-values-of-an-array
+ int len = array.length;
+
+ if (len > 0){
+ array[0] = value;
+ }
+
+ for (int i = 1; i < len; i += i) {
+ System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i);
+ }
+ }
}
Added: poi/trunk/test-data/slideshow/bug60345_Jankovic_final_Retreat_2002.ppt
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/bug60345_Jankovic_final_Retreat_2002.ppt?rev=1769226&view=auto
==============================================================================
Binary file - no diff available.
Propchange: poi/trunk/test-data/slideshow/bug60345_Jankovic_final_Retreat_2002.ppt
------------------------------------------------------------------------------
svn:mime-type = application/vnd.ms-powerpoint
Added: poi/trunk/test-data/slideshow/bug60345_paperfigures.ppt
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/bug60345_paperfigures.ppt?rev=1769226&view=auto
==============================================================================
Binary file - no diff available.
Propchange: poi/trunk/test-data/slideshow/bug60345_paperfigures.ppt
------------------------------------------------------------------------------
svn:mime-type = application/vnd.ms-powerpoint
Added: poi/trunk/test-data/slideshow/bug60345_suba.ppt
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/bug60345_suba.ppt?rev=1769226&view=auto
==============================================================================
Binary file - no diff available.
Propchange: poi/trunk/test-data/slideshow/bug60345_suba.ppt
------------------------------------------------------------------------------
svn:mime-type = application/vnd.ms-powerpoint
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org