Issue #81 Exception not always thrown in Jetty to application when upload part is too big

Issue #82 Request.getPart() that results in Exception still allows other parts to be fetched
This commit is contained in:
Jan Bartel 2016-02-16 17:41:19 +01:00
parent 496be5e05f
commit 11d3448e28
3 changed files with 347 additions and 250 deletions

View File

@ -1489,14 +1489,13 @@ public class RequestTest
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce); request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
//We should get an error when we getParams if there was a problem parsing the multipart //We should get an error when we getParams if there was a problem parsing the multipart
request.getParameter("xxx"); request.getPart("xxx");
//A 200 response is actually wrong here //A 200 response is actually wrong here
} }
catch (RuntimeException e) catch (RuntimeException e)
{ {
response.sendError(500); response.sendError(500);
} }
} }
} }

View File

@ -60,6 +60,7 @@ public class MultiPartInputStreamParser
protected MultipartConfigElement _config; protected MultipartConfigElement _config;
protected String _contentType; protected String _contentType;
protected MultiMap<Part> _parts; protected MultiMap<Part> _parts;
protected Exception _err;
protected File _tmpDir; protected File _tmpDir;
protected File _contextTmpDir; protected File _contextTmpDir;
protected boolean _deleteOnExit; protected boolean _deleteOnExit;
@ -414,6 +415,9 @@ public class MultiPartInputStreamParser
throws IOException throws IOException
{ {
parse(); parse();
throwIfError();
Collection<List<Part>> values = _parts.values(); Collection<List<Part>> values = _parts.values();
List<Part> parts = new ArrayList<>(); List<Part> parts = new ArrayList<>();
for (List<Part> o: values) for (List<Part> o: values)
@ -436,20 +440,36 @@ public class MultiPartInputStreamParser
throws IOException throws IOException
{ {
parse(); parse();
throwIfError();
return _parts.getValue(name, 0); return _parts.getValue(name, 0);
} }
/**
* Throws an exception if one has been latched.
*
* @throws IOException
*/
protected void throwIfError ()
throws IOException
{
if (_err != null)
{
if (_err instanceof IOException)
throw (IOException)_err;
if (_err instanceof IllegalStateException)
throw (IllegalStateException)_err;
throw new IllegalStateException(_err);
}
}
/** /**
* Parse, if necessary, the multipart stream. * Parse, if necessary, the multipart stream.
* *
* @throws IOException if unable to parse
*/ */
protected void parse () protected void parse ()
throws IOException
{ {
//have we already parsed the input? //have we already parsed the input?
if (_parts != null) if (_parts != null || _err != null)
return; return;
//initialize //initialize
@ -460,6 +480,8 @@ public class MultiPartInputStreamParser
if (_contentType == null || !_contentType.startsWith("multipart/form-data")) if (_contentType == null || !_contentType.startsWith("multipart/form-data"))
return; return;
try
{
//sort out the location to which to write the files //sort out the location to which to write the files
if (_config.getLocation() == null) if (_config.getLocation() == null)
@ -749,6 +771,11 @@ public class MultiPartInputStreamParser
if (!lastPart) if (!lastPart)
throw new IOException("Incomplete parts"); throw new IOException("Incomplete parts");
} }
catch (Exception e)
{
_err = e;
}
}
public void setDeleteOnExit(boolean deleteOnExit) public void setDeleteOnExit(boolean deleteOnExit)
{ {

View File

@ -355,6 +355,42 @@ public class MultiPartInputStreamTest
} }
} }
@Test
public void testRequestTooBigThrowsErrorOnGetParts ()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
MultiPartInputStreamParser mpis = new MultiPartInputStreamParser(new ByteArrayInputStream(_multi.getBytes()),
_contentType,
config,
_tmpDir);
mpis.setDeleteOnExit(true);
Collection<Part> parts = null;
//cause parsing
try
{
parts = mpis.getParts();
fail("Request should have exceeded maxRequestSize");
}
catch (IllegalStateException e)
{
assertTrue(e.getMessage().startsWith("Request exceeds maxRequestSize"));
}
//try again
try
{
parts = mpis.getParts();
fail("Request should have exceeded maxRequestSize");
}
catch (IllegalStateException e)
{
assertTrue(e.getMessage().startsWith("Request exceeds maxRequestSize"));
}
}
@Test @Test
public void testFileTooBig() public void testFileTooBig()
throws Exception throws Exception
@ -377,6 +413,41 @@ public class MultiPartInputStreamTest
} }
} }
@Test
public void testFileTooBigThrowsErrorOnGetParts()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
MultiPartInputStreamParser mpis = new MultiPartInputStreamParser(new ByteArrayInputStream(_multi.getBytes()),
_contentType,
config,
_tmpDir);
mpis.setDeleteOnExit(true);
Collection<Part> parts = null;
try
{
parts = mpis.getParts(); //caused parsing
fail("stuff.txt should have been larger than maxFileSize");
}
catch (IllegalStateException e)
{
assertTrue(e.getMessage().startsWith("Multipart Mime part"));
}
//test again after the parsing
try
{
parts = mpis.getParts(); //caused parsing
fail("stuff.txt should have been larger than maxFileSize");
}
catch (IllegalStateException e)
{
assertTrue(e.getMessage().startsWith("Multipart Mime part"));
}
}
@Test @Test
public void testPartFileNotDeleted () throws Exception public void testPartFileNotDeleted () throws Exception
{ {