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 <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2019-07-18 12:13:35 -05:00
parent aef58168d0
commit 36294ef0da
3 changed files with 28 additions and 6 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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++;
}
}
}