|
|
@@ -20,12 +20,13 @@ package org.apache.poi.hslf.blip; |
|
|
|
import static org.apache.logging.log4j.util.Unbox.box; |
|
|
|
|
|
|
|
import java.awt.Dimension; |
|
|
|
import java.io.ByteArrayInputStream; |
|
|
|
import java.io.EOFException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.zip.InflaterInputStream; |
|
|
|
|
|
|
|
import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; |
|
|
|
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; |
|
|
|
import org.apache.logging.log4j.LogManager; |
|
|
|
import org.apache.logging.log4j.Logger; |
|
|
@@ -84,41 +85,42 @@ public final class PICT extends Metafile { |
|
|
|
} |
|
|
|
|
|
|
|
private byte[] read(byte[] data, int pos) throws IOException { |
|
|
|
ByteArrayInputStream bis = new ByteArrayInputStream(data); |
|
|
|
Header header = new Header(); |
|
|
|
header.read(data, pos); |
|
|
|
long bs_exp = (long)pos + header.getSize(); |
|
|
|
long bs_act = IOUtils.skipFully(bis, bs_exp); |
|
|
|
if (bs_exp != bs_act) { |
|
|
|
throw new EOFException(); |
|
|
|
} |
|
|
|
byte[] chunk = new byte[4096]; |
|
|
|
try (UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(header.getWmfSize())) { |
|
|
|
try (InflaterInputStream inflater = new InflaterInputStream(bis)) { |
|
|
|
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 |
|
|
|
Arrays.fill(chunk, (byte) 0); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
int lastLen = chunk.length - 1; |
|
|
|
while (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()); |
|
|
|
try (InputStream bis = new UnsynchronizedByteArrayInputStream(data)) { |
|
|
|
long bs_act = IOUtils.skipFully(bis, bs_exp); |
|
|
|
if (bs_exp != bs_act) { |
|
|
|
throw new EOFException(); |
|
|
|
} |
|
|
|
byte[] chunk = new byte[4096]; |
|
|
|
try (UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(header.getWmfSize())) { |
|
|
|
try (InflaterInputStream inflater = new InflaterInputStream(bis)) { |
|
|
|
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 |
|
|
|
Arrays.fill(chunk, (byte) 0); |
|
|
|
} |
|
|
|
out.write(chunk, 0, lastLen); |
|
|
|
} catch (Exception e) { |
|
|
|
int lastLen = chunk.length - 1; |
|
|
|
while (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.atError().withThrowable(e).log("PICT zip-stream is invalid, read as much as possible. Uncompressed length of header: {} / Read bytes: {}", box(header.getWmfSize()), box(out.size())); |
|
|
|
} |
|
|
|
// End of picture marker for PICT is 0x00 0xFF |
|
|
|
LOG.atError().withThrowable(e).log("PICT zip-stream is invalid, read as much as possible. Uncompressed length of header: {} / Read bytes: {}", box(header.getWmfSize()), box(out.size())); |
|
|
|
return out.toByteArray(); |
|
|
|
} |
|
|
|
return out.toByteArray(); |
|
|
|
} |
|
|
|
} |
|
|
|
|