Skip to content

Commit 0c2d96c

Browse files
authored
Fixes #949 (#950)
* Introduced try/finally block to guarantee consumable content InputStream is closed
1 parent a7de554 commit 0c2d96c

File tree

2 files changed

+39
-33
lines changed

2 files changed

+39
-33
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This patch release:
77
* Ensures that after successful JWS signature verification, an application-configured Base64Url `Decoder` output is
88
used to construct a `Jws` instance (instead of JJWT's default decoder). See
99
[Issue 947](https://github.com/jwtk/jjwt/issues/947).
10+
* Fixes a decompression memory leak in concurrent/multi-threaded environments introduced in 0.12.0 when decompressing JWTs with a `zip` header of `GZIP`. See [Issue 949](https://github.com/jwtk/jjwt/issues/949).
1011

1112
### 0.12.5
1213

impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -597,43 +597,48 @@ private byte[] verifySignature(final TokenizedJwt tokenized, final JwsHeader jws
597597
Claims claims = null;
598598
byte[] payloadBytes = payload.getBytes();
599599
if (payload.isConsumable()) {
600-
601-
InputStream in = payload.toInputStream();
602-
603-
if (!hasContentType(header)) { // If there is a content type set, then the application using JJWT is expected
604-
// to convert the byte payload themselves based on this content type
605-
// https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.10 :
606-
//
607-
// "This parameter is ignored by JWS implementations; any processing of this
608-
// parameter is performed by the JWS application."
609-
//
610-
Map<String, ?> claimsMap = null;
611-
try {
612-
// if deserialization fails, we'll need to rewind to convert to a byte array. So if
613-
// mark/reset isn't possible, we'll need to buffer:
614-
if (!in.markSupported()) {
615-
in = new BufferedInputStream(in);
616-
in.mark(0);
617-
}
618-
claimsMap = deserialize(new UncloseableInputStream(in) /* Don't close in case we need to rewind */, "claims");
619-
} catch (DeserializationException | MalformedJwtException ignored) { // not JSON, treat it as a byte[]
600+
InputStream in = null;
601+
try {
602+
in = payload.toInputStream();
603+
604+
if (!hasContentType(header)) { // If there is a content type set, then the application using JJWT is expected
605+
// to convert the byte payload themselves based on this content type
606+
// https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.10 :
607+
//
608+
// "This parameter is ignored by JWS implementations; any processing of this
609+
// parameter is performed by the JWS application."
610+
//
611+
Map<String, ?> claimsMap = null;
612+
try {
613+
// if deserialization fails, we'll need to rewind to convert to a byte array. So if
614+
// mark/reset isn't possible, we'll need to buffer:
615+
if (!in.markSupported()) {
616+
in = new BufferedInputStream(in);
617+
in.mark(0);
618+
}
619+
claimsMap = deserialize(new UncloseableInputStream(in) /* Don't close in case we need to rewind */, "claims");
620+
} catch (DeserializationException |
621+
MalformedJwtException ignored) { // not JSON, treat it as a byte[]
620622
// String msg = "Invalid claims: " + e.getMessage();
621623
// throw new MalformedJwtException(msg, e);
622-
} finally {
623-
Streams.reset(in);
624-
}
625-
if (claimsMap != null) {
626-
try {
627-
claims = new DefaultClaims(claimsMap);
628-
} catch (Throwable t) {
629-
String msg = "Invalid claims: " + t.getMessage();
630-
throw new MalformedJwtException(msg);
624+
} finally {
625+
Streams.reset(in);
626+
}
627+
if (claimsMap != null) {
628+
try {
629+
claims = new DefaultClaims(claimsMap);
630+
} catch (Throwable t) {
631+
String msg = "Invalid claims: " + t.getMessage();
632+
throw new MalformedJwtException(msg);
633+
}
631634
}
632635
}
633-
}
634-
if (claims == null) {
635-
// consumable, but not claims, so convert to byte array:
636-
payloadBytes = Streams.bytes(in, "Unable to convert payload to byte array.");
636+
if (claims == null) {
637+
// consumable, but not claims, so convert to byte array:
638+
payloadBytes = Streams.bytes(in, "Unable to convert payload to byte array.");
639+
}
640+
} finally { // always ensure closed per https://github.com/jwtk/jjwt/issues/949
641+
Objects.nullSafeClose(in);
637642
}
638643
}
639644

0 commit comments

Comments
 (0)