From 36294ef0da95f63545c027ce78a9159f153dca82 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 18 Jul 2019 12:13:35 -0500 Subject: [PATCH] Issue #3888 - Fixing for truncated long to int + Allowing CachedHttpContent._contentLengthValue actually hold the `long` resource size (for the 4G variant on test) + Allowing BufferUtil to not throw Exception if resource length is a positive value, but exceeds Integer.MAX_VALUE, opting instead to return a null to prevent excessive memory usage. (fixes the 10G variant of test) Signed-off-by: Joakim Erdfelt --- .../eclipse/jetty/server/CachedContentFactory.java | 6 +++--- .../java/org/eclipse/jetty/util/BufferUtil.java | 14 +++++++++++--- .../org/eclipse/jetty/webapp/HugeResourceTest.java | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java index faa20fe8da0..5f76fcdb436 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CachedContentFactory.java @@ -386,7 +386,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory { private final String _key; private final Resource _resource; - private final int _contentLengthValue; + private final long _contentLengthValue; private final HttpField _contentType; private final String _characterEncoding; private final MimeTypes.Type _mimeType; @@ -415,7 +415,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory _lastModified = _lastModifiedValue == -1 ? null : new PreEncodedHttpField(HttpHeader.LAST_MODIFIED, DateGenerator.formatDate(_lastModifiedValue)); - _contentLengthValue = exists ? (int)resource.length() : 0; + _contentLengthValue = exists ? resource.length() : 0; _contentLength = new PreEncodedHttpField(HttpHeader.CONTENT_LENGTH, Long.toString(_contentLengthValue)); if (_cachedFiles.incrementAndGet() > _maxCachedFiles) @@ -558,7 +558,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory ByteBuffer buffer2 = CachedContentFactory.this.getIndirectBuffer(_resource); if (buffer2 == null) - LOG.warn("Could not load " + this); + LOG.warn("Could not load indirect buffer from " + this); else if (_indirectBuffer.compareAndSet(null, buffer2)) { buffer = buffer2; diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java index 7b948213a3f..a0eceef6307 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java @@ -971,11 +971,19 @@ public class BufferUtil public static ByteBuffer toBuffer(Resource resource, boolean direct) throws IOException { - int len = (int)resource.length(); + long len = resource.length(); if (len < 0) throw new IllegalArgumentException("invalid resource: " + resource + " len=" + len); - ByteBuffer buffer = direct ? BufferUtil.allocateDirect(len) : BufferUtil.allocate(len); + if (len > Integer.MAX_VALUE) + { + // This method cannot handle resources of this size. + return null; + } + + int ilen = (int)len; + + ByteBuffer buffer = direct ? BufferUtil.allocateDirect(ilen) : BufferUtil.allocate(ilen); int pos = BufferUtil.flipToFill(buffer); if (resource.getFile() != null) @@ -984,7 +992,7 @@ public class BufferUtil { try (InputStream is = resource.getInputStream()) { - BufferUtil.readFrom(is, len, buffer); + BufferUtil.readFrom(is, ilen, buffer); } } BufferUtil.flipToFlush(buffer, pos); diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java index 09d9747772f..5a7afe13813 100644 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java @@ -160,6 +160,8 @@ public class HugeResourceTest HttpURLConnection http = (HttpURLConnection)destUri.toURL().openConnection(); assertThat("HTTP Response Code", http.getResponseCode(), is(200)); + dumpResponseHeaders(http); + // if a Content-Length is provided, test it String contentLength = http.getHeaderField("Content-Length"); if (contentLength != null) @@ -186,4 +188,16 @@ public class HugeResourceTest // Verify the file download size assertThat("Downloaded Files Size: " + filename, Files.size(outputFile), is(expectedSize)); } + + private void dumpResponseHeaders(HttpURLConnection http) + { + int i = 0; + String value; + while ((value = http.getHeaderField(i)) != null) + { + String key = http.getHeaderFieldKey(i); + System.err.printf(" %s: %s%n", key, value); + i++; + } + } }