mirror of https://github.com/jwtk/jjwt.git
Refactored DeflateCompressionCodec to eliminate memory leak. Refactored GzipCompressionCodec and AbstractCompressionCodec to utilize consistent logic across compression algorithms. Resolves #392.
This commit is contained in:
parent
1b5b89304a
commit
af72fabbf3
|
@ -1,10 +1,14 @@
|
|||
## Release Notes
|
||||
|
||||
### 0.10.7
|
||||
|
||||
This patch release fixes a [memory leak](https://github.com/jwtk/jjwt/issues/392) found in the DEFLATE compression
|
||||
codec implementation.
|
||||
|
||||
### 0.10.6
|
||||
|
||||
This patch release updates the jackson-databind version to 2.9.8 to address a critical security vulnerability in that
|
||||
library. It also updates .travis.yml to remove deprecated builds and to "trick" travis into building with Oracle
|
||||
JDK 1.7 as this library still supports that Java version even if Travis no longer does.
|
||||
library.
|
||||
|
||||
### 0.10.5
|
||||
|
||||
|
|
|
@ -18,8 +18,12 @@ package io.jsonwebtoken.impl.compression;
|
|||
import io.jsonwebtoken.CompressionCodec;
|
||||
import io.jsonwebtoken.CompressionException;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import io.jsonwebtoken.lang.Objects;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract class that asserts arguments and wraps IOException with CompressionException.
|
||||
|
@ -28,6 +32,44 @@ import java.io.IOException;
|
|||
*/
|
||||
public abstract class AbstractCompressionCodec implements CompressionCodec {
|
||||
|
||||
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||
//TODO: make protected on a minor release
|
||||
interface StreamWrapper {
|
||||
OutputStream wrap(OutputStream out) throws IOException;
|
||||
}
|
||||
|
||||
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||
//TODO: make protected on a minor release
|
||||
byte[] readAndClose(InputStream input) throws IOException {
|
||||
byte[] buffer = new byte[512];
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(buffer.length);
|
||||
int read;
|
||||
try {
|
||||
read = input.read(buffer); //assignment separate from loop invariant check for code coverage checks
|
||||
while (read != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
read = input.read(buffer);
|
||||
}
|
||||
} finally {
|
||||
Objects.nullSafeClose(input);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||
//TODO: make protected on a minor release
|
||||
byte[] writeAndClose(byte[] payload, StreamWrapper wrapper) throws IOException {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
|
||||
OutputStream compressionStream = wrapper.wrap(outputStream);
|
||||
try {
|
||||
compressionStream.write(payload);
|
||||
compressionStream.flush();
|
||||
} finally {
|
||||
Objects.nullSafeClose(compressionStream);
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this method to do the actual work of compressing the payload
|
||||
*
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
package io.jsonwebtoken.impl.compression;
|
||||
|
||||
import io.jsonwebtoken.lang.Objects;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
/**
|
||||
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate compression algorithm</a>.
|
||||
|
@ -32,43 +30,25 @@ public class DeflateCompressionCodec extends AbstractCompressionCodec {
|
|||
|
||||
private static final String DEFLATE = "DEF";
|
||||
|
||||
private static final StreamWrapper WRAPPER = new StreamWrapper() {
|
||||
@Override
|
||||
public OutputStream wrap(OutputStream out) {
|
||||
return new DeflaterOutputStream(out);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getAlgorithmName() {
|
||||
return DEFLATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] doCompress(byte[] payload) throws IOException {
|
||||
|
||||
Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
|
||||
|
||||
ByteArrayOutputStream outputStream = null;
|
||||
DeflaterOutputStream deflaterOutputStream = null;
|
||||
try {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
deflaterOutputStream = new DeflaterOutputStream(outputStream, deflater, true);
|
||||
|
||||
deflaterOutputStream.write(payload, 0, payload.length);
|
||||
deflaterOutputStream.flush();
|
||||
return outputStream.toByteArray();
|
||||
} finally {
|
||||
Objects.nullSafeClose(outputStream, deflaterOutputStream);
|
||||
}
|
||||
protected byte[] doCompress(byte[] payload) throws IOException {
|
||||
return writeAndClose(payload, WRAPPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] doDecompress(byte[] compressed) throws IOException {
|
||||
InflaterOutputStream inflaterOutputStream = null;
|
||||
ByteArrayOutputStream decompressedOutputStream = null;
|
||||
|
||||
try {
|
||||
decompressedOutputStream = new ByteArrayOutputStream();
|
||||
inflaterOutputStream = new InflaterOutputStream(decompressedOutputStream);
|
||||
inflaterOutputStream.write(compressed);
|
||||
inflaterOutputStream.flush();
|
||||
return decompressedOutputStream.toByteArray();
|
||||
} finally {
|
||||
Objects.nullSafeClose(decompressedOutputStream, inflaterOutputStream);
|
||||
}
|
||||
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
||||
return readAndClose(new InflaterInputStream(new ByteArrayInputStream(compressed)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
package io.jsonwebtoken.impl.compression;
|
||||
|
||||
import io.jsonwebtoken.CompressionCodec;
|
||||
import io.jsonwebtoken.lang.Objects;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
|
@ -33,43 +32,25 @@ public class GzipCompressionCodec extends AbstractCompressionCodec implements Co
|
|||
|
||||
private static final String GZIP = "GZIP";
|
||||
|
||||
private static final StreamWrapper WRAPPER = new StreamWrapper() {
|
||||
@Override
|
||||
public OutputStream wrap(OutputStream out) throws IOException {
|
||||
return new GZIPOutputStream(out);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getAlgorithmName() {
|
||||
return GZIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
||||
byte[] buffer = new byte[512];
|
||||
|
||||
ByteArrayOutputStream outputStream = null;
|
||||
GZIPInputStream gzipInputStream = null;
|
||||
ByteArrayInputStream inputStream = null;
|
||||
|
||||
try {
|
||||
inputStream = new ByteArrayInputStream(compressed);
|
||||
gzipInputStream = new GZIPInputStream(inputStream);
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
int read = gzipInputStream.read(buffer);
|
||||
while (read != -1) {
|
||||
outputStream.write(buffer, 0, read);
|
||||
read = gzipInputStream.read(buffer);
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
} finally {
|
||||
Objects.nullSafeClose(inputStream, gzipInputStream, outputStream);
|
||||
}
|
||||
protected byte[] doCompress(byte[] payload) throws IOException {
|
||||
return writeAndClose(payload, WRAPPER);
|
||||
}
|
||||
|
||||
protected byte[] doCompress(byte[] payload) throws IOException {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
GZIPOutputStream compressorOutputStream = new GZIPOutputStream(outputStream, true);
|
||||
try {
|
||||
compressorOutputStream.write(payload, 0, payload.length);
|
||||
compressorOutputStream.finish();
|
||||
return outputStream.toByteArray();
|
||||
} finally {
|
||||
Objects.nullSafeClose(compressorOutputStream, outputStream);
|
||||
}
|
||||
@Override
|
||||
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
||||
return readAndClose(new GZIPInputStream(new ByteArrayInputStream(compressed)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue