dgaudet 99/01/25 10:12:43
Modified: src CHANGES src/modules/standard mod_speling.c Log: Fix O(n^2) memory consumption in mod_speling. (Tested by Renaud Bruyeron <[EMAIL PROTECTED]> and Eric Prud'hommeaux <[EMAIL PROTECTED]>) Revision Changes Path 1.1222 +4 -1 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.1221 retrieving revision 1.1222 diff -u -r1.1221 -r1.1222 --- CHANGES 1999/01/21 19:17:07 1.1221 +++ CHANGES 1999/01/25 18:12:36 1.1222 @@ -1,7 +1,10 @@ Changes with Apache 1.3.5 + *) Fix O(n^2) memory consumption in mod_speling. [Dean Gaudet] + *) SECURITY: Avoid some buffer overflow problems when escaping - quoted strings. [Rick Perry <[EMAIL PROTECTED]>] + quoted strings. (This overflow was on the heap and we believe + impossible to exploit.) [Rick Perry <[EMAIL PROTECTED]>] *) Let src/Configure be aware of CFLAGS options starting with plus signs as it's the case for the HP/UX compiler. 1.31 +48 -30 apache-1.3/src/modules/standard/mod_speling.c Index: mod_speling.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_speling.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- mod_speling.c 1999/01/01 19:05:14 1.30 +++ mod_speling.c 1999/01/25 18:12:41 1.31 @@ -428,10 +428,13 @@ * returned. */ else { - char *t; pool *p; table *notes; + pool *sub_pool; + array_header *t; + array_header *v; + if (r->main == NULL) { p = r->pool; notes = r->notes; @@ -441,16 +444,22 @@ notes = r->main->notes; } + sub_pool = ap_make_sub_pool(p); + t = ap_make_array(sub_pool, candidates->nelts * 8 + 8, + sizeof(char *)); + v = ap_make_array(sub_pool, candidates->nelts * 5, + sizeof(char *)); + /* Generate the response text. */ - /* - * Since the text is expanded by repeated calls of - * t = pstrcat(p, t, ".."), we can avoid a little waste - * of memory by adding the header AFTER building the list. - * XXX: FIXME: find a way to build a string concatenation - * without repeatedly requesting new memory - * XXX: FIXME: Limit the list to a maximum number of entries - */ - t = ""; + + *(const char **)ap_push_array(t) = + "The document name you requested (<code>"; + *(const char **)ap_push_array(t) = r->uri; + *(const char **)ap_push_array(t) = + "</code>) could not be found on this server.\n" + "However, we found documents with names similar " + "to the one you requested.<p>" + "Available documents:\n<ul>\n"; for (i = 0; i < candidates->nelts; ++i) { char *vuri; @@ -458,16 +467,24 @@ reason = sp_reason_str[(int) (variant[i].quality)]; /* The format isn't very neat... */ - vuri = ap_pstrcat(p, url, variant[i].name, r->path_info, + vuri = ap_pstrcat(sub_pool, url, variant[i].name, r->path_info, (r->parsed_uri.query != NULL) ? "?" : "", (r->parsed_uri.query != NULL) ? r->parsed_uri.query : "", NULL); - ap_table_mergen(r->subprocess_env, "VARIANTS", - ap_pstrcat(p, "\"", vuri, "\";\"", - reason, "\"", NULL)); - t = ap_pstrcat(p, t, "<li><a href=\"", vuri, - "\">", vuri, "</a> (", reason, ")\n", NULL); + *(const char **)ap_push_array(v) = "\""; + *(const char **)ap_push_array(v) = vuri; + *(const char **)ap_push_array(v) = "\";\""; + *(const char **)ap_push_array(v) = reason; + *(const char **)ap_push_array(v) = "\""; + + *(const char **)ap_push_array(t) = "<li><a href=\""; + *(const char **)ap_push_array(t) = vuri; + *(const char **)ap_push_array(t) = "\">"; + *(const char **)ap_push_array(t) = vuri; + *(const char **)ap_push_array(t) = "</a> ("; + *(const char **)ap_push_array(t) = reason; + *(const char **)ap_push_array(t) = ")\n"; /* * when we have printed the "close matches" and there are @@ -479,30 +496,31 @@ if (i > 0 && i < candidates->nelts - 1 && variant[i].quality != SP_VERYDIFFERENT && variant[i + 1].quality == SP_VERYDIFFERENT) { - t = ap_pstrcat(p, t, + *(const char **)ap_push_array(t) = "</ul>\nFurthermore, the following related " - "documents were found:\n<ul>\n", NULL); + "documents were found:\n<ul>\n"; } } - t = ap_pstrcat(p, "The document name you requested (<code>", - r->uri, - "</code>) could not be found on this server.\n" - "However, we found documents with names similar " - "to the one you requested.<p>" - "Available documents:\n<ul>\n", t, "</ul>\n", NULL); + *(const char **)ap_push_array(t) = "</ul>\n"; /* If we know there was a referring page, add a note: */ if (ref != NULL) { - t = ap_pstrcat(p, t, + *(const char **)ap_push_array(t) = "Please consider informing the owner of the " - "<a href=\"", ref, - "\">referring page</a> " - "about the broken link.\n", - NULL); + "<a href=\""; + *(const char **)ap_push_array(t) = ref; + *(const char **)ap_push_array(t) = "\">referring page</a> " + "about the broken link.\n"; } + /* Pass our table to http_protocol.c (see mod_negotiation): */ - ap_table_setn(notes, "variant-list", t); + ap_table_setn(notes, "variant-list", ap_array_pstrcat(p, t, 0)); + + ap_table_mergen(r->subprocess_env, "VARIANTS", + ap_array_pstrcat(p, v, ',')); + + ap_destroy_pool(sub_pool); ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r, ref ? "Spelling fix: %s: %d candidates from %s"