httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bri...@apache.org
Subject cvs commit: httpd-2.0/server protocol.c
Date Sat, 06 Jul 2002 01:53:37 GMT
brianp      2002/07/05 18:53:37

  Modified:    server   protocol.c
  Log:
  Eliminated the use of AP_MODE_SPECULATIVE brigade reads to check
  for request header continuation lines.  Instead, ap_get_mime_headers_core()
  now sets aside each line of input until it sees the next line.  If the
  next line starts with a tab, it is appended to the previous one; otherwise,
  the previous line is added to the request headers table.
  
  This reduces the number of temporary buckets that must be created
  and destroyed to read in a request.
  
  Revision  Changes    Path
  1.111     +77 -29    httpd-2.0/server/protocol.c
  
  Index: protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/protocol.c,v
  retrieving revision 1.110
  retrieving revision 1.111
  diff -u -r1.110 -r1.111
  --- protocol.c	4 Jul 2002 17:05:25 -0000	1.110
  +++ protocol.c	6 Jul 2002 01:53:37 -0000	1.111
  @@ -743,7 +743,10 @@
   
   AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb)
   {
  -    char* field;
  +    char *last_field = NULL;
  +    apr_size_t last_len;
  +    apr_size_t alloc_len = 0;
  +    char *field;
       char *value;
       apr_size_t len;
       int fields_read = 0;
  @@ -758,10 +761,11 @@
        */
       while(1) {
           apr_status_t rv;
  +        int folded = 0;
   
           field = NULL;
           rv = ap_rgetline(&field, DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2,
  -                         &len, r, 1, bb);
  +                         &len, r, 0, bb);
   
           /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
            * finding the end-of-line.  This is only going to happen if it
  @@ -787,39 +791,83 @@
               return;
           }
   
  -        /* Found a blank line, stop. */
  -        if (len == 0) {
  -            break;
  -        }
  +        if (last_field != NULL) {
  +            if ((len > 0) && (*field == '\t')) {
  +                /* This line is a continuation of the preceding line(s),
  +                 * so append it to the line that we've set aside.
  +                 * Note: this uses a power-of-two allocator to avoid
  +                 * doing O(n) allocs and using O(n^2) space for
  +                 * continuations that span many many lines.
  +                 */
  +                if (last_len + len > alloc_len) {
  +                    char *fold_buf;
  +                    alloc_len += alloc_len;
  +                    if (last_len + len > alloc_len) {
  +                        alloc_len = last_len + len;
  +                    }
  +                    fold_buf = (char *)apr_palloc(r->pool, alloc_len);
  +                    memcpy(fold_buf, last_field, last_len);
  +                    last_field = fold_buf;
  +                }
  +                memcpy(last_field + last_len, field, len +1); /* +1 for nul */
  +                last_len += len;
  +                folded = 1;
  +            }
  +            else {
  +
  +                if (r->server->limit_req_fields
  +                    && (++fields_read > r->server->limit_req_fields))
{
  +                    r->status = HTTP_BAD_REQUEST;
  +                    apr_table_setn(r->notes, "error-notes",
  +                                   "The number of request header fields "
  +                                   "exceeds this server's limit.");
  +                    return;
  +                }
  +
  +                if (!(value = strchr(last_field, ':'))) { /* Find ':' or    */
  +                    r->status = HTTP_BAD_REQUEST;      /* abort bad request */
  +                    apr_table_setn(r->notes, "error-notes",
  +                                   apr_pstrcat(r->pool,
  +                                               "Request header field is "
  +                                               "missing ':' separator.<br />\n"
  +                                               "<pre>\n",
  +                                               ap_escape_html(r->pool,
  +                                                              last_field),
  +                                               "</pre>\n", NULL));
  +                    return;
  +                }
  +
  +                *value = '\0';
  +                ++value;
  +                while (*value == ' ' || *value == '\t') {
  +                    ++value;            /* Skip to start of value   */
  +                }
  +
  +                apr_table_addn(tmp_headers, last_field, value);
  +
  +                /* reset the alloc_len so that we'll allocate a new
  +                 * buffer if we have to do any more folding: we can't
  +                 * use the previous buffer because its contents are
  +                 * now part of tmp_headers
  +                 */
  +                alloc_len = 0;
   
  -        if (r->server->limit_req_fields
  -            && (++fields_read > r->server->limit_req_fields)) {
  -            r->status = HTTP_BAD_REQUEST;
  -            apr_table_setn(r->notes, "error-notes",
  -                           "The number of request header fields exceeds "
  -                           "this server's limit.");
  -            return;
  +            } /* end if current line is not a continuation starting with tab */
           }
   
  -        if (!(value = strchr(field, ':'))) {    /* Find the colon separator */
  -            r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
  -            apr_table_setn(r->notes, "error-notes",
  -                           apr_pstrcat(r->pool,
  -                                       "Request header field is missing "
  -                                       "colon separator.<br />\n"
  -                                       "<pre>\n",
  -                                       ap_escape_html(r->pool, field),
  -                                       "</pre>\n", NULL));
  -            return;
  +        /* Found a blank line, stop. */
  +        if (len == 0) {
  +            break;
           }
   
  -        *value = '\0';
  -        ++value;
  -        while (*value == ' ' || *value == '\t') {
  -            ++value;            /* Skip to start of value   */
  +        /* Keep track of this line so that we can parse it on
  +         * the next loop iteration.  (In the folded case, last_field
  +         * has been updated already.)
  +         */
  +        if (!folded) {
  +            last_field = field;
  +            last_len = len;
           }
  -
  -        apr_table_addn(tmp_headers, field, value);
       }
   
       apr_table_overlap(r->headers_in, tmp_headers, APR_OVERLAP_TABLES_MERGE);
  
  
  

Mime
View raw message