stas 2003/02/06 18:30:53 Modified: src/modules/perl modperl_filter.c Log: we have no choice but to truncate wb->outbuf to the size of 'len'. All kind of weird problems pop-up when the previous request was proper and the current request has messed up with headers, because modperl_cgi_header_parse (actually the ap_scan_script_header_err_strs) will get things messed up because it expects a buffer with real data only. Revision Changes Path 1.50 +24 -23 modperl-2.0/src/modules/perl/modperl_filter.c Index: modperl_filter.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.c,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- modperl_filter.c 7 Feb 2003 00:07:42 -0000 1.49 +++ modperl_filter.c 7 Feb 2003 02:30:52 -0000 1.50 @@ -8,11 +8,28 @@ apr_bucket_alloc_t *ba = (*wb->filters)->c->bucket_alloc; apr_bucket_brigade *bb; apr_bucket *bucket; - + const char *work_buf = buf; + if (wb->header_parse) { request_rec *r = wb->r; const char *bodytext = NULL; - int status = modperl_cgi_header_parse(r, (char *)buf, &bodytext); + int status; + /* + * since wb->outcnt is persistent between requests, if the + * current response is shorter than the size of wb->outcnt + * it may include data from the previous request at the + * end. When this function receives a pointer to + * wb->outbuf as 'buf', modperl_cgi_header_parse may + * return that irrelevant data as part of 'bodytext'. So + * to avoid this risk, we create a new buffer of size 'len' + * XXX: if buf wasn't 'const char *buf' we could simply do + * buf[len] = '\0' + */ + if (len < strlen(buf)) { + work_buf = (char *)apr_pcalloc(wb->pool, sizeof(char*)*len); + memcpy((void*)work_buf, buf, len); + } + status = modperl_cgi_header_parse(r, (char *)work_buf, &bodytext); wb->header_parse = 0; /* only once per-request */ @@ -26,32 +43,16 @@ /* XXX: bodytext == NULL here */ return status; } - - if (!bodytext) { + else if (!bodytext) { return APR_SUCCESS; } - else { - len -= (bodytext - buf); - buf = bodytext; - /* - * since wb->outbuf is persistent between requests, if the - * current response is shorter than the size of wb->outbuf - * it may include data from the previous request at the - * end. When this function receives a pointer to - * wb->outbuf as 'buf', modperl_cgi_header_parse may - * return that irrelevant data as part of 'bodytext'. So - * to avoid this risk, we check whether there is any real - * data to send and if not return. - */ - if (!len) { - return APR_SUCCESS; - } - } - + + len -= (bodytext - work_buf); + work_buf = bodytext; } bb = apr_brigade_create(wb->pool, ba); - bucket = apr_bucket_transient_create(buf, len, ba); + bucket = apr_bucket_transient_create(work_buf, len, ba); APR_BRIGADE_INSERT_TAIL(bb, bucket); MP_TRACE_f(MP_FUNC, "buffer length=%d\n", len);