~james-page/ubuntu/maverick/tomcat6/fix-654549

« back to all changes in this revision

Viewing changes to java/org/apache/coyote/http11/InternalNioInputBuffer.java

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2011-03-24 10:10:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110324101009-fuvqwo4gsi1lcw7c
Tags: 6.0.28-2ubuntu1.2
* SECURITY UPDATE: directory traversal via incorrect ServetContext
  attribute (LP: #717396)
  - debian/patches/0012-CVE-2010-3718.patch: mark as read only in
    java/org/apache/catalina/core/StandardContext.java.
  - CVE-2010-3718
* SECURITY UPDATE: cross-site scripting in HTML Manager interface
  - debian/patches/0013-CVE-2011-0013.patch: properly filter values in
    java/org/apache/catalina/manager/{HTMLManagerServlet.java,
    StatusTransformer.java}.
  - CVE-2011-0013
* SECURITY UPDATE: denial of service via NIOS HTTP connector
  (LP: #714239, LP: #717396)
  - debian/patches/0014-CVE-2011-0534.patch: enforce proper size in
    java/org/apache/coyote/http11/InternalNioInputBuffer.java.
  - CVE-2011-0534

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
 */
42
42
public class InternalNioInputBuffer implements InputBuffer {
43
43
 
 
44
    /**
 
45
     * Logger.
 
46
     */
 
47
    private static final org.apache.juli.logging.Log log =
 
48
        org.apache.juli.logging.LogFactory.getLog(InternalNioInputBuffer.class);
44
49
 
45
50
    // -------------------------------------------------------------- Constants
46
51
 
57
62
        this.request = request;
58
63
        headers = request.getMimeHeaders();
59
64
 
60
 
        buf = new byte[headerBufferSize];
61
 
//        if (headerBufferSize < (8 * 1024)) {
62
 
//            bbuf = ByteBuffer.allocateDirect(6 * 1500);
63
 
//        } else {
64
 
//            bbuf = ByteBuffer.allocateDirect((headerBufferSize / 1500 + 1) * 1500);
65
 
//        }
 
65
        this.headerBufferSize = headerBufferSize;
66
66
 
67
67
        inputStreamInputBuffer = new SocketInputBuffer();
68
68
 
189
189
    protected int lastActiveFilter;
190
190
 
191
191
 
 
192
    /**
 
193
     * Maximum allowed size of the HTTP request line plus headers.
 
194
     */
 
195
    private final int headerBufferSize;
 
196
 
 
197
    /**
 
198
     * Known size of the NioChannel read buffer.
 
199
     */
 
200
    private int socketReadBufferSize;
 
201
 
 
202
    /**
 
203
     * Additional size we allocate to the buffer to be more effective when
 
204
     * skipping empty lines that may precede the request.
 
205
     */
 
206
    private static final int skipBlankLinesSize = 1024;
 
207
 
 
208
    /**
 
209
     * How many bytes in the buffer are occupied by skipped blank lines that
 
210
     * precede the request.
 
211
     */
 
212
    private int skipBlankLinesBytes;
 
213
 
192
214
    // ------------------------------------------------------------- Properties
193
215
 
194
216
 
197
219
     */
198
220
    public void setSocket(NioChannel socket) {
199
221
        this.socket = socket;
 
222
        socketReadBufferSize = socket.getBufHandler().getReadBuffer().capacity();
 
223
        int bufLength = skipBlankLinesSize + headerBufferSize
 
224
                + socketReadBufferSize;
 
225
        if (buf == null || buf.length < bufLength) {
 
226
            buf = new byte[bufLength];
 
227
        }
200
228
    }
201
229
    
202
230
    /**
421
449
                    if (useAvailableData) {
422
450
                        return false;
423
451
                    }
 
452
                    // Ignore bytes that were read
 
453
                    pos = lastValid = 0;
424
454
                    // Do a simple read with a short timeout
425
455
                    if ( readSocket(true, false)==0 ) return false;
426
456
                }
427
457
                chr = buf[pos++];
428
458
            } while ((chr == Constants.CR) || (chr == Constants.LF));
429
459
            pos--;
 
460
            if (pos >= skipBlankLinesSize) {
 
461
                // Move data, to have enough space for further reading
 
462
                // of headers and body
 
463
                System.arraycopy(buf, pos, buf, 0, lastValid - pos);
 
464
                lastValid -= pos;
 
465
                pos = 0;
 
466
            }
 
467
            skipBlankLinesBytes = pos;
430
468
            parsingRequestLineStart = pos;
431
 
            parsingRequestLinePhase = 1;
432
 
        } 
433
 
        if ( parsingRequestLinePhase == 1 ) {
434
 
            // Mark the current buffer position
435
 
            
436
 
            if (pos >= lastValid) {
437
 
                if (useAvailableData) {
438
 
                    return false;
439
 
                }
440
 
                // Do a simple read with a short timeout
441
 
                if ( readSocket(true, false)==0 ) return false;
442
 
            }
443
469
            parsingRequestLinePhase = 2;
444
470
        }
445
471
        if ( parsingRequestLinePhase == 2 ) {
578
604
    
579
605
    private void expand(int newsize) {
580
606
        if ( newsize > buf.length ) {
 
607
            if (parsingHeader) {
 
608
                throw new IllegalArgumentException(
 
609
                        sm.getString("iib.requestheadertoolarge.error"));
 
610
            }
 
611
            // Should not happen
 
612
            log.warn("Expanding buffer size. Old size: " + buf.length
 
613
                    + ", new size: " + newsize, new Exception());
581
614
            byte[] tmp = new byte[newsize];
582
615
            System.arraycopy(buf,0,tmp,0,buf.length);
583
616
            buf = tmp;
639
672
        if (status == HeaderParseStatus.DONE) {
640
673
            parsingHeader = false;
641
674
            end = pos;
 
675
            // Checking that
 
676
            // (1) Headers plus request line size does not exceed its limit
 
677
            // (2) There are enough bytes to avoid expanding the buffer when
 
678
            // reading body
 
679
            // Technically, (2) is technical limitation, (1) is logical
 
680
            // limitation to enforce the meaning of headerBufferSize
 
681
            // From the way how buf is allocated and how blank lines are being
 
682
            // read, it should be enough to check (1) only.
 
683
            if (end - skipBlankLinesBytes > headerBufferSize
 
684
                    || buf.length - end < socketReadBufferSize) {
 
685
                throw new IllegalArgumentException(
 
686
                        sm.getString("iib.requestheadertoolarge.error"));
 
687
            }
642
688
            return true;
643
689
        } else {
644
690
            return false;
889
935
            // Do a simple read with a short timeout
890
936
            read = readSocket(timeout,block)>0;
891
937
        } else {
892
 
 
893
 
            if (buf.length - end < 4500) {
894
 
                // In this case, the request header was really large, so we allocate a 
895
 
                // brand new one; the old one will get GCed when subsequent requests
896
 
                // clear all references
897
 
                buf = new byte[buf.length];
898
 
                end = 0;
899
 
            }
900
 
            pos = end;
901
 
            lastValid = pos;
 
938
            lastValid = pos = end;
902
939
            // Do a simple read with a short timeout
903
940
            read = readSocket(timeout, block)>0;
904
941
        }