You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Roy T. Fielding" <fi...@kiwi.ICS.UCI.EDU> on 1997/03/14 05:03:09 UTC

Re: [PATCH] "Type Map file bug causes 100% CPU and mem leak"

I have included a new version of Petr's patch below, since his wasn't
quite complete and the other mod_negotiation.c changes have been
applied separately.

.....Roy

In message <19...@boco.fee.vutbr.cz>, Petr Lampa writes:
>> Submitter: weave@dtcc.edu
>> Operating system: OTHER:DG/UX, version: 4.11
>> Version of Apache Used: 1.2B7
>> Extra Modules used: None
>> URL exhibiting problem: Not on your life! :)
>> 
>> Symptoms:
>> --
>> If a trailing slash is included after a type map
>> file URL, apache goes into a constant write state,
>> dropping the connection doesn't stop it, it consumes
>> 100% of CPU, and a huge memory leak starts.
>> 
>> I tried to reproduce it successfully on a Linux 
>> box running the RedHat distribution (apache 1.1.1)
>> 
>> In this case, it hung the entire system. This is
>> a dual-pentium so it shouldn't have consumed BOTH
>> CPUs... 
>> --
>
>Confirmed. It's in handle_map_file() (mod_negotiation.c):
>   ...
>   udir = make_dirstr (r->pool, r->uri, count_dirs (r->uri));
>   udir = escape_uri(r->pool, udir);
>   internal_redirect (make_full_path (r->pool, udir, best->file_name), r);
>   return OK;
>
>request is "GET /tst.var/", where /tst.var is map file, then
>r->uri = "/tst.var/" -> count_dirs(r->uri) is 2 -> udir = "/tst.var/"
>best->file_name = tst2.html
>make_full_path (new uri) = "/tst.var/tst2.html"
>
>This redirection enters handle_map_file() again, and the situation repeats
>indefinitely (until stack overflows). 
>
>Discussion:
>- first part takes out path_info from r->uri (taken from add_cgi_vars())
>- second part generates new full uri with negotiated file name and path_info.
>  (in the example above new_uri="/tst2.html/", which is wrong if /tst2.html
>  is file and the error response is properly returned).
>  It's not necessary to use make_full_path, since udir always contains "/" 
>  at the end (see make_dirstr).
>
>+++
>And one more question: it's quite possible to cause such negotiation
>loop with bad map file. The existence of the file specified 
>in the "uri:" directive in map file is not verified and redirection
>to this file may result in another negotiation. What about verifying
>existence of the file using stat() and ignoring such variant, 
>if file doesn't exist?

I suggest holding that thought til after 1.2, since it is an expensive
operation to second-guess the configuration on every request.

>							Petr
>-- 
>Department of Computer Science and Engineering  E-mail: lampa@fee.vutbr.cz
>Faculty of El. Engineering and Comp. Science	Phone: (+420 5) 7275/225,111
>Technical University of Brno			Fax:  (+420 5) 41211141
>Bozetechova 2, 612 66 Brno, Czech Republic

New patch:

Index: util_script.h
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.h,v
retrieving revision 1.13
diff -c -r1.13 util_script.h
*** util_script.h	1997/01/01 18:10:47	1.13
--- util_script.h	1997/03/14 03:56:53
***************
*** 61,66 ****
--- 61,67 ----
  char **create_argv_cmd(pool *p, char *av0, const char *args, char *path);
  #endif
  char **create_environment(pool *p, table *t);
+ int find_path_info(char *uri, char *path_info);
  void add_cgi_vars(request_rec *r);
  void add_common_vars(request_rec *r);
  #define scan_script_header(a1,a2) scan_script_header_err(a1,a2,NULL)
Index: util_script.c
===================================================================
RCS file: /export/home/cvs/apache/src/util_script.c,v
retrieving revision 1.46
diff -c -r1.46 util_script.c
*** util_script.c	1997/03/03 05:01:44	1.46
--- util_script.c	1997/03/14 03:56:54
***************
*** 213,219 ****
   * and find as much of the two that match as possible.
   */
  
! static int find_path_info (char *uri, char *path_info)
  {
      int lu = strlen(uri);
      int lp = strlen(path_info);
--- 213,219 ----
   * and find as much of the two that match as possible.
   */
  
! int find_path_info (char *uri, char *path_info)
  {
      int lu = strlen(uri);
      int lp = strlen(path_info);
Index: mod_negotiation.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_negotiation.c,v
retrieving revision 1.35
diff -c -r1.35 mod_negotiation.c
*** mod_negotiation.c	1997/03/14 03:27:32	1.35
--- mod_negotiation.c	1997/03/14 03:56:54
***************
*** 62,67 ****
--- 62,68 ----
  #include "http_request.h"
  #include "http_core.h"
  #include "http_log.h"
+ #include "util_script.h"
  
  /* define TCN_02 to allow for Holtman I-D transparent negotiation.
   * This file currently implements the draft-02, except for
***************
*** 1875,1883 ****
      if (na_result == na_not_applied)
          set_neg_headers(r, neg, na_not_applied);
  
      udir = make_dirstr (r->pool, r->uri, count_dirs (r->uri));
      udir = escape_uri(r->pool, udir);
!     internal_redirect (make_full_path (r->pool, udir, best->file_name), r);
      return OK;
  }
  
--- 1876,1888 ----
      if (na_result == na_not_applied)
          set_neg_headers(r, neg, na_not_applied);
  
+     if (r->path_info && *r->path_info) {
+         r->uri[find_path_info(r->uri, r->path_info)] = '\0';
+     }
      udir = make_dirstr (r->pool, r->uri, count_dirs (r->uri));
      udir = escape_uri(r->pool, udir);
!     internal_redirect(pstrcat(r->pool, udir, best->file_name, r->path_info,
!                               NULL), r);
      return OK;
  }