X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=9a05b306be69cf36baf09108cb22a3495d1f92a9;hp=509be632b3ca4c870900a8ec513ecd2414192878;hb=1c79e7655de8bcab545c9f044ac6197b233d9ec1;hpb=2e92b76d8f022f87691967eca118f917f780c057 diff --git a/jcc.c b/jcc.c index 509be632..9a05b306 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.223 2009/02/09 21:21:16 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.230 2009/03/07 13:09:17 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,34 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.223 2009/02/09 21:21:16 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.230 2009/03/07 13:09:17 fabiankeil + * Change csp->expected_content and_csp->expected_content_length from + * size_t to unsigned long long to reduce the likelihood of integer + * overflows that would let us close the connection prematurely. + * Bug found while investigating #2669131, reported by cyberpatrol. + * + * Revision 1.229 2009/03/07 11:17:01 fabiankeil + * Fix compiler warning. + * + * Revision 1.228 2009/03/06 20:30:13 fabiankeil + * Log unsigned values as such. + * + * Revision 1.227 2009/03/02 19:18:11 fabiankeil + * Streamline parse_http_request()'s prototype. As + * cparser pointed out it doesn't actually use csp. + * + * Revision 1.226 2009/03/01 18:28:24 fabiankeil + * Help clang understand that we aren't dereferencing + * NULL pointers here. + * + * Revision 1.225 2009/02/19 18:09:32 fabiankeil + * Unbreak build without FEATURE_CONNECTION_KEEP_ALIVE. + * Noticed by David. + * + * Revision 1.224 2009/02/14 15:32:04 fabiankeil + * Add the request URL to the timeout message in chat(). + * Suggested by Lee. + * * Revision 1.223 2009/02/09 21:21:16 fabiankeil * Now that init_log_module() is called earlier, call show_version() * later on from main() directly so it doesn't get called for --help @@ -1879,7 +1907,7 @@ static void send_crunch_response(const struct client_state *csp, struct http_res /* Log that the request was crunched and why. */ log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url); - log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %d", + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u", csp->ip_addr_str, http->ocmd, status_code, rsp->content_length); /* Clean up and return */ @@ -1936,7 +1964,7 @@ static int request_contains_null_bytes(const struct client_state *csp, char *buf } while (tmp_len < len); log_error(LOG_LEVEL_ERROR, "%s\'s request contains at least one NULL byte " - "(length=%d, strlen=%d).", csp->ip_addr_str, len, c_len); + "(length=%d, strlen=%u).", csp->ip_addr_str, len, c_len); log_error(LOG_LEVEL_HEADER, "Offending request data with NULL bytes turned into \'°\' characters: %s", buf); @@ -2105,7 +2133,7 @@ static jb_err change_request_destination(struct client_state *csp) log_error(LOG_LEVEL_INFO, "Rewrite detected: %s", csp->headers->first->str); free_http_request(http); - err = parse_http_request(csp->headers->first->str, http, csp); + err = parse_http_request(csp->headers->first->str, http); if (JB_ERR_OK != err) { log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.", @@ -2142,9 +2170,10 @@ static jb_err change_request_destination(struct client_state *csp) * FALSE otherwise. * *********************************************************************/ -static int server_response_is_complete(struct client_state *csp, size_t content_length) +static int server_response_is_complete(struct client_state *csp, + unsigned long long content_length) { - int content_length_known = (csp->flags & CSP_FLAG_CONTENT_LENGTH_SET); + int content_length_known = !!(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET); if (!strcmpic(csp->http->gpc, "HEAD")) { @@ -2168,8 +2197,38 @@ static int server_response_is_complete(struct client_state *csp, size_t content_ return (content_length_known && ((0 == csp->expected_content_length) || (csp->expected_content_length <= content_length))); } + + +/********************************************************************* + * + * Function : wait_for_alive_connections + * + * Description : Waits for alive connections to timeout. + * + * Parameters : N/A + * + * Returns : N/A + * + *********************************************************************/ +static void wait_for_alive_connections() +{ + int connections_alive = close_unusable_connections(); + + while (0 < connections_alive) + { + log_error(LOG_LEVEL_CONNECT, + "Waiting for %d connections to timeout.", + connections_alive); + sleep(60); + connections_alive = close_unusable_connections(); + } + + log_error(LOG_LEVEL_CONNECT, "No connections to wait for left."); + +} #endif /* FEATURE_CONNECTION_KEEP_ALIVE */ + /********************************************************************* * * Function : mark_server_socket_tainted @@ -2313,7 +2372,7 @@ static jb_err receive_client_request(struct client_state *csp) } #endif /* def FEATURE_FORCE_LOAD */ - err = parse_http_request(req, http, csp); + err = parse_http_request(req, http); freez(req); if (JB_ERR_OK != err) { @@ -2522,7 +2581,7 @@ static void chat(struct client_state *csp) jb_socket maxfd; int server_body; int ms_iis5_hack = 0; - size_t byte_count = 0; + unsigned long long byte_count = 0; int forwarded_connect_retries = 0; int max_forwarded_connect_retries = csp->config->forwarded_connect_retries; const struct forward_spec *fwd; @@ -2557,6 +2616,7 @@ static void chat(struct client_state *csp) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ + return; } /* @@ -2760,15 +2820,15 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "Looks like we read the last chunk together with " "the server headers. We better stop reading."); - byte_count = (size_t)(csp->iob->eod - csp->iob->cur); + byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur); csp->expected_content_length = byte_count; csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET; } if (server_body && server_response_is_complete(csp, byte_count)) { log_error(LOG_LEVEL_CONNECT, - "Done reading from server. Expected content length: %d. " - "Actual content length: %d. Most recently received: %d.", + "Done reading from server. Expected content length: %llu. " + "Actual content length: %llu. Most recently received: %d.", csp->expected_content_length, byte_count, len); len = 0; /* @@ -2882,7 +2942,7 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "Looks like we reached the end of the last chunk. " "We better stop reading."); - csp->expected_content_length = byte_count + (size_t)len; + csp->expected_content_length = byte_count + (unsigned long long)len; csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET; } } @@ -2951,7 +3011,8 @@ static void chat(struct client_state *csp) } if (write_socket(csp->cfd, hdr, strlen(hdr)) - || write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length)) + || write_socket(csp->cfd, + ((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length)) { log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); freez(hdr); @@ -3035,7 +3096,7 @@ static void chat(struct client_state *csp) * we just flushed. len will be added a few lines below, * hdrlen doesn't matter for LOG_LEVEL_CLF. */ - byte_count = (size_t)flushed; + byte_count = (unsigned long long)flushed; freez(hdr); content_filter = NULL; server_body = 1; @@ -3050,7 +3111,7 @@ static void chat(struct client_state *csp) return; } } - byte_count += (size_t)len; + byte_count += (unsigned long long)len; continue; } else @@ -3092,11 +3153,11 @@ static void chat(struct client_state *csp) * Since we have to wait for more from the server before * we can parse the headers we just continue here. */ - int header_offset = csp->iob->cur - header_start; + long header_offset = csp->iob->cur - header_start; assert(csp->iob->cur >= header_start); - byte_count += (size_t)(len - header_offset); + byte_count += (unsigned long long)(len - header_offset); log_error(LOG_LEVEL_CONNECT, "Continuing buffering headers. " - "byte_count: %d. header_offset: %d. len: %d.", + "byte_count: %llu. header_offset: %d. len: %d.", byte_count, header_offset, len); continue; } @@ -3196,7 +3257,7 @@ static void chat(struct client_state *csp) return; } - byte_count += (size_t)len; + byte_count += (unsigned long long)len; } else { @@ -3204,9 +3265,9 @@ static void chat(struct client_state *csp) * XXX: the header lenght should probably * be calculated by get_server_headers(). */ - int header_length = csp->iob->cur - header_start; + long header_length = csp->iob->cur - header_start; assert(csp->iob->cur > header_start); - byte_count += (size_t)(len - header_length); + byte_count += (unsigned long long)(len - header_length); } /* we're finished with the server's header */ @@ -3241,48 +3302,22 @@ static void chat(struct client_state *csp) csp->content_length = byte_count; } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->flags & CSP_FLAG_CONTENT_LENGTH_SET) && (csp->expected_content_length != byte_count)) { log_error(LOG_LEVEL_CONNECT, - "Received %d bytes while expecting %d.", + "Received %llu bytes while expecting %llu.", byte_count, csp->expected_content_length); mark_server_socket_tainted(csp); } +#endif - log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d", + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu", csp->ip_addr_str, http->ocmd, csp->content_length); } -/********************************************************************* - * - * Function : wait_for_alive_connections - * - * Description : Waits for alive connections to timeout. - * - * Parameters : N/A - * - * Returns : N/A - * - *********************************************************************/ -static void wait_for_alive_connections() -{ - int connections_alive = close_unusable_connections(); - - while (0 < connections_alive) - { - log_error(LOG_LEVEL_CONNECT, - "Waiting for %d connections to timeout.", - connections_alive); - sleep(60); - connections_alive = close_unusable_connections(); - } - - log_error(LOG_LEVEL_CONNECT, "No connections to wait for left."); - -} - /********************************************************************* * * Function : serve