Summary: | maxHttpHeaderSize maybe case ArrayIndexOutOfBoundsException | ||
---|---|---|---|
Product: | Tomcat 8 | Reporter: | yangkun <yklovejava> |
Component: | Connectors | Assignee: | Tomcat Developers Mailing List <dev> |
Status: | RESOLVED FIXED | ||
Severity: | normal | ||
Priority: | P2 | ||
Version: | 8.0.18 | ||
Target Milestone: | ---- | ||
Hardware: | PC | ||
OS: | All |
Description
yangkun
2015-01-28 08:16:03 UTC
The exception corresponds to what is actually occurring, so it looks fine to me as is. It might be nice to do bounds-checking (or not) and use an application exception instead of AAOOBE. Getting an AAOOBE usually indicates to me that there is a software flaw, not a data flaw. If check the maxHttpHeaderSize careful, the error may be subdivide the following cases: 1. the request uri more than maxHttpHeaderSize, it should be a 414-request url too long 2. the request entity more than maxHttpHeaderSize, it should be a 413-request entity too large I think in this respect, Tomcat can be do better, :) (In reply to yangkun from comment #3) Your diagnosis is wrong. We are not talking about request here. It is response (the status line of a HTTP response) that does not fit the buffer used by status line and HTTP headers. Generally, AbstractOutputBuffer.write(..) methods do perform a length check, but numerous headerBuffer[pos++] = (COLON|SP|CR|LF) do not. A simple fix may be to change AOB.checkLengthBeforeWrite(int length) method to assume that the usable buffer length is less by 4 bytes. There are no more than 4 bytes added directly to the buffer after the write. (4 = 2 bytes for CR-LF + 2 bytes for CR-LF added by AOB.endHeaders()) The result will be that the checkLengthBeforeWrite() method will throw a org.apache.coyote.http11.HeadersTooLargeException (a subclass of an IllegalStateException), essentially resulting in the same server-side error. Fixed in trunk and Tomcat 8 (r1657460), will be in 8.0.19 onwards. Fixed in Tomcat 7 by r1657591, will be in 7.0.60 onwards. - 4 bytes added is the correct fixe ? The method sendHeader --> write(name); headerBuffer[pos++] = Constants.COLON; headerBuffer[pos++] = Constants.SP; write(value); headerBuffer[pos++] = Constants.CR; headerBuffer[pos++] = Constants.LF; call the method write(MessageBytes mb) 2 times and at the end of this method, call the method write(mb.getByteChunk() this method call checkLengthBeforeWrite(length) In the first call write(name) --> this block that increments 2 positions is not called headerBuffer[pos++] = Constants.COLON; headerBuffer[pos++] = Constants.SP; The class AbstractHttp11Processor method private void prepareResponse() call the class AOB --> int size = headers.size(); for (int i = 0; i < size; i++) { getOutputBuffer().sendHeader(headers.getName(i), headers.getValue(i)); } getOutputBuffer().endHeaders(); in other words, I believe: the method checkLengthBeforeWrite in the first call if (pos + length > headerBuffer.length) the method checkLengthBeforeWrite in the second call if (pos + length + 2 > headerBuffer.length) and if have a third scan after getOutputBuffer().endHeaders() - there is no such verification - and also would not make sense if (pos + length + 4 > headerBuffer.length) and would be after getOutputBuffer().endHeaders() Please check. (In reply to Shelson Ferrari from comment #7) > - 4 bytes added is the correct fixe ? Yes. |