We've just been looking at a case of an (admittently) doggy resolver library which led through non-ASCII chars (as part of some i18n efford) and hence allowed for alien chars to end up in the log files. Which royally screwed the operator.
The patch below goes a bit further than the current escaping added recently - and adds a %t to the ap_snprintf(). Specically around some resover returns. Posting here as it may be of use for some people. I am too far removed from day to day httpd dev to even consider committing this. Have fun, Dw Index: src/ApacheCore.def =================================================================== RCS file: /home/cvs/apache-1.3/src/ApacheCore.def,v retrieving revision 1.35 diff -u -r1.35 ApacheCore.def --- src/ApacheCore.def 18 Jun 2002 04:19:46 -0000 1.35 +++ src/ApacheCore.def 18 Dec 2003 14:05:51 -0000 @@ -447,3 +447,4 @@ ap_getline @439 ap_get_chunk_size @440 ap_escape_logitem @441 + ap_escape_snbuff @442 Index: src/ap/ap_snprintf.c =================================================================== RCS file: /home/cvs/apache-1.3/src/ap/ap_snprintf.c,v retrieving revision 1.54 diff -u -r1.54 ap_snprintf.c --- src/ap/ap_snprintf.c 3 Feb 2003 17:13:17 -0000 1.54 +++ src/ap/ap_snprintf.c 18 Dec 2003 14:05:51 -0000 @@ -118,6 +118,10 @@ */ #define NUM_BUF_SIZE 512 +/* Max size for escaped string (%t) argument. + */ +#define STR_BUF_SIZE (MAX_STRING_LEN) + /* * cvt.c - IEEE floating point formatting routines for FreeBSD * from GNU libc-4.6.27. Modified to be thread safe. @@ -714,6 +718,7 @@ /* * Default variable settings */ + char strbuff[ STR_BUF_SIZE ]; adjust = RIGHT; alternate_form = print_sign = print_blank = NO; pad_char = ' '; @@ -915,9 +920,14 @@ case 's': + case 't': s = va_arg(ap, char *); if (s != NULL) { - s_len = strlen(s); + if (*fmt == 't') { + s_len = ap_escape_snbuff(strbuff,sizeof(strbuff),s); + s = strbuff; + } else + s_len = strlen(s); if (adjust_precision && precision < s_len) s_len = precision; } Index: src/include/httpd.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.374 diff -u -r1.374 httpd.h @@ -1028,6 +1029,7 @@ API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname, unsigned port, const request_rec *r); API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str); +API_EXPORT(int) ap_escape_snbuff(char *buff, int size, const char *str); API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source, size_t buflen); API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s); Index: src/main/http_core.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v retrieving revision 1.327 diff -u -r1.327 http_core.c @@ -3669,7 +3671,7 @@ } if ((r->uri[0] != '/') && strcmp(r->uri, "*")) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Invalid URI in request %s", r->the_request); + "Invalid URI in request %t", r->the_request); return BAD_REQUEST; } @@ -4003,7 +4005,7 @@ if (r->method_number == M_INVALID) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Invalid method in request %s", + "Invalid method in request %t", ap_escape_logitem(r->pool, r->the_request)); return NOT_IMPLEMENTED; } @@ -4016,7 +4018,7 @@ if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, - "File does not exist: %s",r->path_info ? + "File does not exist: %t",r->path_info ? ap_pstrcat(r->pool, r->filename, r->path_info, NULL) : r->filename); return HTTP_NOT_FOUND; Index: src/main/http_log.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_log.c,v retrieving revision 1.97 diff -u -r1.97 http_log.c --- src/main/http_log.c 14 Dec 2003 18:16:50 -0000 1.97 +++ src/main/http_log.c 18 Dec 2003 14:05:54 -0000 @@ -549,13 +549,13 @@ API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s) { - ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err); + ap_log_error(APLOG_MARK, APLOG_ERR, s, "%t", err); } API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file, const char *msg, server_rec *s) { - ap_log_error(file, 0, APLOG_ERR, s, "%s", msg); + ap_log_error(file, 0, APLOG_ERR, s, "%t", msg); } API_EXPORT_NONSTD(void) ap_log_printf(const server_rec *s, const char *fmt, ...) @@ -570,7 +570,7 @@ API_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "access to %s failed for %s, reason: %s", + "access to %t failed for %t, reason: %t", file, ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME), reason); Index: src/main/http_main.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.605 diff -u -r1.605 http_main.c --- src/main/http_main.c 19 Oct 2003 18:00:35 -0000 1.605 +++ src/main/http_main.c 18 Dec 2003 14:05:58 -0000 @@ -1541,7 +1541,7 @@ dirconf = current_conn->server->lookup_defaults; if (!current_conn->keptalive) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, - current_conn->server, "[client %s] %s timed out", + current_conn->server, "[client %t] %s timed out", current_conn->remote_ip, timeout_name ? timeout_name : "request"); } Index: src/main/http_protocol.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v retrieving revision 1.330 diff -u -r1.330 http_protocol.c --- src/main/http_protocol.c 3 Feb 2003 17:13:22 -0000 1.330 +++ src/main/http_protocol.c 18 Dec 2003 14:05:59 -0000 @@ -1252,7 +1252,7 @@ * comes through... */ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "client sent invalid HTTP/0.9 request: HEAD %s", + "client sent invalid HTTP/0.9 request: HEAD %t", r->uri); r->header_only = 0; r->status = HTTP_BAD_REQUEST; @@ -1287,7 +1287,7 @@ r->status = HTTP_BAD_REQUEST; ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "client sent HTTP/1.1 request without hostname " - "(see RFC2616 section 14.23): %s", r->uri); + "(see RFC2616 section 14.23): %t", r->uri); } if (r->status != HTTP_OK) { ap_send_error_response(r, 0); @@ -1316,7 +1316,7 @@ r->status = HTTP_EXPECTATION_FAILED; ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r, "client sent an unrecognized expectation value of " - "Expect: %s", expect); + "Expect: %t", expect); ap_send_error_response(r, 0); (void) ap_discard_request_body(r); ap_log_transaction(r); @@ -1411,7 +1411,7 @@ if (!ap_auth_name(r)) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, - r, "need AuthName: %s", r->uri); + r, "need AuthName: %t", r->uri); return SERVER_ERROR; } @@ -1423,7 +1423,7 @@ if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) { /* Client tried to authenticate using wrong auth scheme */ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "client used wrong authentication scheme: %s", r->uri); + "client used wrong authentication scheme: %t", r->uri); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } @@ -2006,12 +2006,12 @@ if (tenc) { if (strcasecmp(tenc, "chunked")) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Unknown Transfer-Encoding %s", tenc); + "Unknown Transfer-Encoding %t", tenc); return HTTP_NOT_IMPLEMENTED; } if (r->read_body == REQUEST_CHUNKED_ERROR) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "chunked Transfer-Encoding forbidden: %s", r->uri); + "chunked Transfer-Encoding forbidden: %t", r->uri); return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED; } @@ -2049,7 +2049,7 @@ if ((r->read_body == REQUEST_NO_BODY) && (r->read_chunked || (r->remaining > 0))) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "%s with body is not allowed for %s", r->method, r->uri); + "%t with body is not allowed for %t", r->method, r->uri); return HTTP_REQUEST_ENTITY_TOO_LARGE; } @@ -2057,7 +2057,7 @@ if (max_body && ((unsigned long)r->remaining > max_body) && (r->remaining >= 0)) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Request content-length of %s is larger than the configured " + "Request content-length of %t is larger than the configured " "limit of %lu", lenp, max_body); return HTTP_REQUEST_ENTITY_TOO_LARGE; } Index: src/main/http_request.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_request.c,v retrieving revision 1.171 diff -u -r1.171 http_request.c --- src/main/http_request.c 18 Oct 2003 14:15:58 -0000 1.171 +++ src/main/http_request.c 18 Dec 2003 14:06:00 -0000 @@ -296,7 +296,7 @@ else #endif ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "access to %s failed", r->uri); + "access to %t failed", r->uri); return HTTP_FORBIDDEN; } #else @@ -1176,7 +1176,7 @@ { if (status == DECLINED) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r, - "configuration error: couldn't %s: %s", phase, r->uri); + "configuration error: couldn't %s: %t", phase, r->uri); ap_die(SERVER_ERROR, r); } else Index: src/main/http_vhost.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_vhost.c,v retrieving revision 1.35 diff -u -r1.35 http_vhost.c --- src/main/http_vhost.c 3 Feb 2003 17:13:23 -0000 1.35 +++ src/main/http_vhost.c 18 Dec 2003 14:06:00 -0000 @@ -220,7 +220,7 @@ if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, - "Cannot resolve host name %s --- ignoring!", w); + "Cannot resolve host name %t --- ignoring!", w); if (t != NULL) *t = ':'; return NULL; Index: src/main/util.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/util.c,v retrieving revision 1.208 diff -u -r1.208 util.c --- src/main/util.c 14 Dec 2003 18:16:50 -0000 1.208 +++ src/main/util.c 18 Dec 2003 14:06:01 -0000 @ -1469,54 +1512,90 @@ return where; } -/* escape a string for logging */ -API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str) +/* Take the buffer in 'str' and copy it into buff (up to size + * bytes, including the terminating \0) - printing chars from the + * T_ESCAPE_LOGITEM in their escaped format. The function returns + * a count (excluding the terminating \0); useful in combination with + * buff==NULL; which will prevent writing into the buff. + */ +API_EXPORT(int ) ap_escape_snbuff(char *buff, int size, const char *str) { - char *ret; unsigned char *d; const unsigned char *s; + int n = 0; - if (str == NULL) - return NULL; + if (str == NULL || *str == '\0' || size <=0) { + if (buff) + buff[0] = '\0'; + return 0; + } - ret = ap_palloc(p, 4 * strlen(str) + 1); /* Be safe */ - d = (unsigned char *)ret; + d = (unsigned char *)buff; s = (const unsigned char *)str; for (; *s; ++s) { - if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) { - *d++ = '\\'; + if (buff) + *d++ = '\\'; + if (n >= size - 2) + break; switch(*s) { case '\b': - *d++ = 'b'; + if (buff) *d++ = 'b'; break; case '\n': - *d++ = 'n'; + if (buff) *d++ = 'n'; break; case '\r': - *d++ = 'r'; + if (buff) *d++ = 'r'; break; case '\t': - *d++ = 't'; + if (buff) *d++ = 't'; break; case '\v': - *d++ = 'v'; + if (buff) *d++ = 'v'; break; case '\\': case '"': - *d++ = *s; + if (buff) *d++ = *s; break; default: - c2x(*s, d); - *d = 'x'; - d += 3; - } + if (n >= size -3) + break; + if (buff) { + c2x(*s, d); + *d = 'x'; + d += 3; + } + n+=2; + } + n+=2; + } + else { + if (n >= size -1); + break; + if (buff) + *d++ = *s; + n++; } - else - *d++ = *s; } - *d = '\0'; + if (buff) + *d = '\0'; + n++; /* Also count the terminating \0. */ + return n; +} + +/* escape a string for logging */ +API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str) +{ + char *ret; + int n; + + if (str == NULL) + return NULL; + n = 4 * strlen(str) + 1; /* Be safe */ + ret = ap_palloc(p,n); + ap_escape_snbuff(ret,n,str); return ret; } Index: src/main/util_script.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/util_script.c,v retrieving revision 1.167 diff -u -r1.167 util_script.c --- src/main/util_script.c 3 Feb 2003 17:13:23 -0000 1.167 +++ src/main/util_script.c 18 Dec 2003 14:06:02 -0000 @@ -565,7 +565,7 @@ ap_kill_timeout(r); ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "%s: %s", malformed, r->filename); + "%t: %s", malformed, r->filename); return HTTP_INTERNAL_SERVER_ERROR; } Index: src/support/httpd.exp =================================================================== RCS file: /home/cvs/apache-1.3/src/support/httpd.exp,v retrieving revision 1.41 diff -u -r1.41 httpd.exp --- src/support/httpd.exp 17 Jan 2003 12:23:10 -0000 1.41 +++ src/support/httpd.exp 18 Dec 2003 14:06:03 -0000 @@ -107,6 +107,7 @@ ap_error_log2stderr ap_escape_html ap_escape_logitem +ap_escape_snbuff ap_escape_path_segment ap_escape_quotes ap_escape_shell_cmd