Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterOutputStream;

import org.apache.avro.AvroRuntimeException;
import org.apache.avro.util.NonCopyingByteArrayOutputStream;

/**
Expand All @@ -38,6 +39,20 @@
public class DeflateCodec extends Codec {

private static final int DEFAULT_BUFFER_SIZE = 8192;
private static final String MAX_DECOMPRESS_LENGTH_PROPERTY = "org.apache.avro.limits.decompress.maxLength";
private static final long DEFAULT_MAX_DECOMPRESS_LENGTH = 200L * 1024 * 1024; // 200MB default limit

private static long getMaxDecompressLength() {
String prop = System.getProperty(MAX_DECOMPRESS_LENGTH_PROPERTY);
if (prop != null) {
try {
return Long.parseLong(prop);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also accept a negative and 0 as values which are not very sensible.
Probably these should be reported earlier here ?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added validation for <= 0 values with warning log.

} catch (NumberFormatException e) {
// Use default
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should be logged as a WARNING.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added LOG.warn() for NumberFormatException.

}
}
return DEFAULT_MAX_DECOMPRESS_LENGTH;
}

static class Option extends CodecFactory {
private final int compressionLevel;
Expand Down Expand Up @@ -78,10 +93,32 @@ public ByteBuffer compress(ByteBuffer data) throws IOException {

@Override
public ByteBuffer decompress(ByteBuffer data) throws IOException {
long maxLength = getMaxDecompressLength();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to call this method on every decompress().
You can read it once in a static {...} block and reuse it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good advice! Changed to static block initialization with MAX_DECOMPRESS_LENGTH field.

NonCopyingByteArrayOutputStream baos = new NonCopyingByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
try (OutputStream outputStream = new InflaterOutputStream(baos, getInflater())) {
outputStream.write(data.array(), computeOffset(data), data.remaining());
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long totalBytes = 0;

Inflater inflater = getInflater();
inflater.setInput(data.array(), computeOffset(data), data.remaining());

try {
while (!inflater.finished()) {
int len = inflater.inflate(buffer);
if (len == 0 && inflater.needsInput()) {
break;
}
totalBytes += len;
if (totalBytes > maxLength) {
throw new AvroRuntimeException(
"Decompressed size " + totalBytes + " exceeds maximum allowed size " + maxLength
+ ". This can be configured by setting the system property " + MAX_DECOMPRESS_LENGTH_PROPERTY);
}
baos.write(buffer, 0, len);
}
} catch (DataFormatException e) {
throw new IOException("Invalid deflate data", e);
}

return baos.asByteBuffer();
}

Expand Down