-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TCK Challenge] attempting to writing more than content-length bytes #525
Comments
@janbartel actually we don't throw an However, even if we didn't throw (and just set the writer's I think the test should be rewritten as: public void flushBufferTest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
int size = 40;
response.setContentLength(size);
response.setCharacterEncoding(StandardCharsets.ISO_8859_1.name());
PrintWriter pw = response.getWriter();
String testPassed = "Test PASSED";
pw.println(testPassed);
pw.println("x".repeat(size - testPassed.length()));
response.addIntHeader("header1", 12345);
} perhaps the test should also attempt a write to ensure the response is closed, but due to the nature of these tests, that would require state to be remembered and a second request made to check the results. |
@markt-asf any comments on the challenge to the |
TL;DR: the TCK test is correct and consistent with the specification but I think the specification (and hence the test) need to change to better handle the case where more than My reading of the specification as currently written is that as soon as Writing more than
|
@markt-asf Are you sure there is verbage in the current spec saying that the container should truncate a too-large write? Consider the following code: String pileOfPoo = "💩💩💩";
String json = "{value=\"" + pileOfPoo + "\"}";
response.setContentType("application/json");
response.setContentLength(json.length());
response.getOutputStream().print(json); OK this is a programming error, because the string length is not the same as the byte length of a string. But such mistakes are common and often undetected by testing as multi-byte characters are not always tested. Such a bug might only be triggered when a user supplied string with multi-byte characters is received. I seams wrong and dangerous for a container to be able to detect this obviously wrong write, yet to simply truncate the data in the middle of a multi-part UTF-8 character and send the response as if there was no problem at all. Then what should the container do with the excess bytes of the write? should it throw an exception after committing a valid response? To write a valid response and then throw gives us a Schrodinger's cat write that is both successful and a failure and only be observing the actual response sent can we know which. I'm very reluctant to change the Jetty code to send what is known to be an invalid response message just to pass this TCK test. The specification say:
It does not say "the amount of content specified OR GREATER". At no time in the above example must there be a moment when exactly the "amount of content specified in the setContentLength" has been written, unless in the naive implementation of writing byte by byte. All reasonable implementations will write a single We'd like to proceed with this challenge to the TCK. |
This all comes down to the interpretation of
The current wording is not explicit about what happens if an attempt is made to write more than the specified amount. On the basis that the TCK test has been written based on a particular interpretation and that the TCK test has been the same since at least the Servlet 2.4 TCK which is over 20 years old I lean towards the view that the TCK is testing the intended interpretation. Hence my view that the challenge is invalid. All that said, I agree that the current behaviour is less than ideal. Writing more than the specified amount should be treated as an error condition and I am all in favour of updating the Servlet specification and TCK to require this behaviour from the next version. We'll need to handle this happening both before and after the response has been committed but that is true for any situation leading to an internal error so I don't think there is anything new there. I don't think the challenge is valid but if other folks want to view this as valid and go through the process to release an updated TCK I'm not going to object but neither do I have the time to assist. |
Just thinking about how this could be handled, 500 makes sense before the response is committed, however I am not sure what the best approach is if an attempt is made to write too much after the response is committed. My gut feeling is that we should just close the connection / RST_STREAM so the client side is clear that something has gone wrong and this is not a valid response. There are also technically 3 different failure modes here:
|
@stuartwdouglas I think there is a reasonable interpretation of the spec in all cases:
Of these scenarios, I think only c) and f) are controversial. I think @markt-asf is suggesting the following interpretation:
I really can't see these as valid/safe interpretations. Of these scenarios, the current TCK appears to only be testing c), but expecting the behaviour of b). @janbartel's proposal above is to change the test to check behaviour b), which I don't think is controversial (although the proposed code has a bug because it uses println rather than print). I think it would be a good short term compromise to change the TCK test to check scenarios a) b) d) and e), which are the non controversial key scenarios. We could defer testing c) and f) until we have agreed behaviours. We will prepare a PR on the TCK. |
Replace the disputed test (that tests poorly defined behaviour of a bad servlet) with two tests that check the accepted behaviour of a well written servlet. Once there is an accepted interpretation of the behaviour for the bad servlet, additional tests can be added to check that.
I have created PR #680 to change the test to just check the non controversial behaviour of a good servlet. |
Replace the disputed test (that tests poorly defined behaviour of a bad servlet) with two tests that check the accepted behaviour of a well written servlet. Once there is an accepted interpretation of the behaviour for the bad servlet, additional tests can be added to check that.
* Fix #525 FlushBufferTest Replace the disputed test (that tests poorly defined behaviour of a bad servlet) with two tests that check the accepted behaviour of a well written servlet. Once there is an accepted interpretation of the behaviour for the bad servlet, additional tests can be added to check that.
Challenged tests:
com/sun/ts/tests/servlet/spec/httpservletresponse/URLClient.java.flushBufferTest
TCK Version:
servlet-tck-6.0.1
Tested Implementation:
Jetty
Description:
Section 5.7 Closure of Response Object
states that:The
flushBufferTest
does:The test expects a
200
response without the presence ofheader1
and probably that the output has been truncated to 40 bytes.In this case, where the servlet has attempted to write more than the
content-length
number of bytes Jetty will throw anIOException
and return an error500
response.There is nothing in the wording of the spec nor javadoc that prohibits a
500
response, or that specifically requires a200
response with excess bytes ignored. Nor would it make sense to truncate the bytes written tocontent-length
, as some content encodings are mutiibyte and would result in garbage.If the aim of the test is to ensure that excess characters are not written, nor the
header
sent, then the test should accept an error500
response.See also:
jetty/jetty.project#9651
The text was updated successfully, but these errors were encountered: