joes 2004/06/13 19:19:58
Modified: . CHANGES RELEASE STATUS
build version_check.pl
env Makefile.am mod_apreq.c
src apreq.c apreq.h apreq_parsers.c
t parsers.c
Log:
Fix longstanding mod_ssl-related bug: missing apr_bucket_setaside calls on
stored-away transient buckets.
Revision Changes Path
1.38 +5 -0 httpd-apreq-2/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- CHANGES 14 Jun 2004 02:02:23 -0000 1.37
+++ CHANGES 14 Jun 2004 02:19:58 -0000 1.38
@@ -2,6 +2,11 @@
@section v2_04_dev Changes with libapreq2-2.04-dev
+- C API [joes, Scott Hutton]
+ Replace apreq_brigade_copy with more effective APREQ_BRIGADE_COPY
+ macro. Also introduce APREQ_BRIGADE_SETASIDE to deal with buckets
+ that need to be set aside for use in future function calls. mod_ssl
+ generates transient buckets which tickled this bug.
- Perl API [joes]
Separate Apache::Upload module from Apache::Request for
1.8 +1 -1 httpd-apreq-2/RELEASE
Index: RELEASE
===================================================================
RCS file: /home/cvs/httpd-apreq-2/RELEASE,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- RELEASE 12 Jun 2004 17:26:26 -0000 1.7
+++ RELEASE 14 Jun 2004 02:19:58 -0000 1.8
@@ -93,7 +93,7 @@
Be sure to update the libapreq2 documentation. For instructions on
updating
the httpd website, see build/WEBSITE.
-10. Post a final announcement to the [EMAIL PROTECTED], modperl@ and
+10. Post a final announcement to the [EMAIL PROTECTED], [EMAIL PROTECTED],
modperl@ and
apreq-dev@ lists:
Subject: [ANNOUNCE] libapreq2-2.XX-dev release
1.53 +2 -15 httpd-apreq-2/STATUS
Index: STATUS
===================================================================
RCS file: /home/cvs/httpd-apreq-2/STATUS,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- STATUS 12 Jun 2004 17:26:26 -0000 1.52
+++ STATUS 14 Jun 2004 02:19:58 -0000 1.53
@@ -66,7 +66,7 @@
- Bring Perl documentation up to speed.
- - Write parser/hook API documentation.
+ - Write parser/hook API documentation, and add perl glue for the API.
- Add XForms logic to the mfd parser.
@@ -83,19 +83,6 @@
BUGS:
-
- - Strange bug when ssl is enabled & lots of fields are present: see
- http://marc.theaimsgroup.com/?t=107766265600001&r=1&w=2
-
- - Another (possibly related) bug has to do with the mfd
- parser misbehaving on file uploads when ssl is enabled:
- http://marc.theaimsgroup.com/?l=apreq-dev&m=108609005217749&w=2
-
- To fix these ssl bugs above, we need to call apr_bucket_setaside
- on all stored-away buckets. This change will affect all current
parsers
- as well as mod_apreq's filter, so we need to have a decent set
- of ssl tests in place to avoid regressions. I suggest we write
- the tests first before attmepting to muck around in the dark. --joes
- Fix build automake/libtool/autoconf build system so it works
properly on OSX & AIX.
1.12 +0 -1 httpd-apreq-2/build/version_check.pl
Index: version_check.pl
===================================================================
RCS file: /home/cvs/httpd-apreq-2/build/version_check.pl,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- version_check.pl 24 Mar 2004 08:22:47 -0000 1.11
+++ version_check.pl 14 Jun 2004 02:19:58 -0000 1.12
@@ -131,4 +131,3 @@
EOM
}
print "$tool: $saw ok\n";
-exit 0;
1.21 +1 -1 httpd-apreq-2/env/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /home/cvs/httpd-apreq-2/env/Makefile.am,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- Makefile.am 10 Jun 2004 20:51:33 -0000 1.20
+++ Makefile.am 14 Jun 2004 02:19:58 -0000 1.21
@@ -52,7 +52,7 @@
test_clean : cmodules_clean
-MAKE=$(MAKE) @PERL@ t/TEST -clean
- -rm -rf t/htdocs t/logs t/modules t/TEST t/cgi-bin/test_cgi
t/cgi-bin/.libs t/conf/extra.conf
+ -rm -rf t/htdocs t/logs t/modules t/TEST t/core t/core.*
t/cgi-bin/test_cgi t/cgi-bin/.libs t/conf/extra.conf t/conf/ssl/ca
t/conf/ssl/httpd-passphrase.pl
cmodules_clean:
-cd c-modules && $(MAKE) clean
1.41 +16 -19 httpd-apreq-2/env/mod_apreq.c
Index: mod_apreq.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/env/mod_apreq.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- mod_apreq.c 24 Mar 2004 21:51:12 -0000 1.40
+++ mod_apreq.c 14 Jun 2004 02:19:58 -0000 1.41
@@ -409,7 +409,6 @@
if (!ctx->saw_eos) {
if (ctx->status == APR_INCOMPLETE) {
- apr_bucket_brigade *tmp;
apr_off_t len;
rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
@@ -418,10 +417,9 @@
return rv;
}
- tmp = apreq_brigade_copy(bb);
- apr_brigade_length(tmp,0,&len);
+ APREQ_BRIGADE_COPY(ctx->bb, bb);
+ apr_brigade_length(bb, 1, &len);
ctx->bytes_read += len;
- APR_BRIGADE_CONCAT(ctx->bb, tmp);
if (cfg->max_body >= 0 && ctx->bytes_read > cfg->max_body) {
ctx->status = APR_ENOSPC;
@@ -447,6 +445,7 @@
if (APR_BUCKET_IS_EOS(e))
e = APR_BUCKET_NEXT(e);
ctx->spool = apr_brigade_split(bb, e);
+ APREQ_BRIGADE_SETASIDE(ctx->spool,r->pool);
}
}
@@ -459,20 +458,13 @@
return APR_SUCCESS;
}
- if (req == NULL)
- req = apreq_request(r, NULL);
-
}
else if (!ctx->saw_eos) {
- /* prefetch read! */
+ /* bb == NULL, so this is a prefetch read! */
- apr_bucket_brigade *tmp = apr_brigade_create(r->pool,
- apr_bucket_alloc_create(r->pool));
apr_off_t total_read = 0;
-
- if (req == NULL)
- req = apreq_request(r, NULL);
+ bb = apr_brigade_create(ctx->bb->p, ctx->bb->bucket_alloc);
while (total_read < readbytes) {
apr_off_t len;
@@ -483,15 +475,16 @@
break;
}
- rv = ap_get_brigade(f->next, tmp, mode, block, readbytes);
+ rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
if (rv != APR_SUCCESS)
return rv;
- bb = apreq_brigade_copy(tmp);
- apr_brigade_length(bb,0,&len);
+ APREQ_BRIGADE_SETASIDE(bb, r->pool);
+ APREQ_BRIGADE_COPY(ctx->bb, bb);
+
+ apr_brigade_length(bb, 1, &len);
total_read += len;
- apreq_brigade_concat(r, ctx->spool, tmp);
- APR_BRIGADE_CONCAT(ctx->bb, bb);
+ apreq_brigade_concat(r, ctx->spool, bb);
}
ctx->bytes_read += total_read;
@@ -506,8 +499,12 @@
else
return APR_SUCCESS;
- if (ctx->status == APR_INCOMPLETE)
+ if (ctx->status == APR_INCOMPLETE) {
+ if (req == NULL)
+ req = apreq_request(r, NULL);
+
ctx->status = apreq_parse_request(req, ctx->bb);
+ }
return APR_SUCCESS;
}
1.34 +2 -19 httpd-apreq-2/src/apreq.c
Index: apreq.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- apreq.c 4 Jun 2004 22:02:11 -0000 1.33
+++ apreq.c 14 Jun 2004 02:19:58 -0000 1.34
@@ -637,7 +637,7 @@
return s;
}
-/* this function now consumes the brigade, deleting buckets as it goes */
+
APREQ_DECLARE(apr_status_t) apreq_brigade_fwrite(apr_file_t *f,
apr_off_t *wlen,
apr_bucket_brigade *bb)
@@ -649,7 +649,7 @@
*wlen = 0;
for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb);
- e = APR_BRIGADE_FIRST(bb))
+ e = APR_BUCKET_NEXT(e))
{
apr_size_t len;
if (n == APREQ_NELTS) {
@@ -664,7 +664,6 @@
return s;
v[n++].iov_len = len;
- apr_bucket_delete(e);
}
while (n > 0) {
@@ -715,22 +714,6 @@
return NULL;
}
-APREQ_DECLARE(apr_bucket_brigade *)
- apreq_brigade_copy(const apr_bucket_brigade *bb)
-{
- apr_bucket_brigade *copy;
- apr_bucket *e;
-
- copy = apr_brigade_create(bb->p, bb->bucket_alloc);
- for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb);
- e = APR_BUCKET_NEXT(e))
- {
- apr_bucket *c;
- apr_bucket_copy(e, &c);
- APR_BRIGADE_INSERT_TAIL(copy, c);
- }
- return copy;
-}
APREQ_DECLARE(apr_status_t)
apreq_header_attribute(const char *hdr,
1.40 +30 -5 httpd-apreq-2/src/apreq.h
Index: apreq.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- apreq.h 4 Jun 2004 22:02:11 -0000 1.39
+++ apreq.h 14 Jun 2004 02:19:58 -0000 1.40
@@ -391,13 +391,38 @@
APREQ_DECLARE(apr_file_t *) apreq_brigade_spoolfile(apr_bucket_brigade *bb);
/**
- * Duplicate a brigade.
- * @param bb Original brigade.
- * @return New brigade containing a bucket-by-bucket copy of the original.
+ * Set aside all buckets in the brigade.
+ * @param bb Brigade.
+ * @param p Setaside buckets into this pool.
*/
-APREQ_DECLARE(apr_bucket_brigade *)
- apreq_brigade_copy(const apr_bucket_brigade *bb);
+#define APREQ_BRIGADE_SETASIDE(bb,p) do { \
+ apr_bucket *e; \
+ for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); \
+ e = APR_BUCKET_NEXT(e)) \
+ { \
+ apr_bucket_setaside(e, p); \
+ } \
+} while (0)
+
+
+/* Copy a brigade.
+ * @param d (destination) Copied buckets are appended to this brigade.
+ * @param s (source) Brigade to copy from.
+ * @remark s == d is undefined.
+ */
+
+#define APREQ_BRIGADE_COPY(d,s) do { \
+ apr_bucket *e; \
+ for (e = APR_BRIGADE_FIRST(s); e != APR_BRIGADE_SENTINEL(s); \
+ e = APR_BUCKET_NEXT(e)) \
+ { \
+ apr_bucket *c; \
+ apr_bucket_copy(e, &c); \
+ APR_BRIGADE_INSERT_TAIL(d, c); \
+ } \
+} while (0)
+
/**
* Search a header string for the value of a particular named attribute.
1.46 +32 -12 httpd-apreq-2/src/apreq_parsers.c
Index: apreq_parsers.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_parsers.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- apreq_parsers.c 4 Jun 2004 22:02:11 -0000 1.45
+++ apreq_parsers.c 14 Jun 2004 02:19:58 -0000 1.46
@@ -261,7 +261,7 @@
break;
}
}
-
+ APREQ_BRIGADE_SETASIDE(ctx->bb, pool);
return APR_INCOMPLETE;
}
@@ -604,6 +604,7 @@
MFD_UPLOAD,
MFD_ERROR
} status;
+ apr_bucket *eos;
};
@@ -707,7 +708,6 @@
return APR_EOF;
if (! APR_BUCKET_IS_FILE(last)) {
- apr_bucket_brigade *bb;
apr_file_t *file;
apr_off_t len, max_brigade = apreq_env_max_brigade(env,-1);
@@ -725,7 +725,7 @@
if (s != APR_SUCCESS)
return s;
- s = apreq_brigade_fwrite(file, &wlen, apreq_brigade_copy(out));
+ s = apreq_brigade_fwrite(file, &wlen, out);
if (s != APR_SUCCESS)
return s;
@@ -750,7 +750,10 @@
APR_BRIGADE_INSERT_TAIL(out, e);
}
+ /* Write the remaining buckets to disk, then delete them. */
s = apreq_brigade_fwrite(f->fd, &wlen, in);
+ apr_brigade_cleanup(in);
+
if (s == APR_SUCCESS)
last->length += wlen;
return s;
@@ -768,6 +771,7 @@
if (parser->ctx == NULL) {
char *ct;
apr_size_t blen;
+ apr_bucket_alloc_t *bucket_alloc = apr_bucket_alloc_create(pool);
ctx = apr_pcalloc(pool, sizeof *ctx);
@@ -793,8 +797,9 @@
ctx->hdr_parser = apreq_make_parser(pool, "", apreq_parse_headers,
NULL,NULL);
ctx->info = NULL;
- ctx->bb = apr_brigade_create(pool, bb->bucket_alloc);
- ctx->in = apr_brigade_create(pool, bb->bucket_alloc);
+ ctx->bb = apr_brigade_create(pool, bucket_alloc);
+ ctx->in = apr_brigade_create(pool, bucket_alloc);
+ ctx->eos = apr_bucket_eos_create(bucket_alloc);
ctx->status = MFD_INIT;
parser->ctx = ctx;
@@ -809,8 +814,11 @@
case MFD_INIT:
{
+ apr_bucket *e = APR_BRIGADE_LAST(ctx->bb);
s = split_on_bdry(ctx->bb, bb, NULL, ctx->bdry + 2);
if (s != APR_SUCCESS) {
+ APREQ_BRIGADE_SETASIDE(bb, pool);
+ APREQ_BRIGADE_SETASIDE(ctx->bb, pool);
return s;
}
ctx->status = MFD_NEXTLINE;
@@ -822,6 +830,8 @@
apr_status_t s;
s = split_on_bdry(ctx->bb, bb, NULL, CRLF);
if (s != APR_SUCCESS) {
+ APREQ_BRIGADE_SETASIDE(bb, pool);
+ APREQ_BRIGADE_SETASIDE(ctx->bb, pool);
return s;
}
ctx->status = MFD_HEADER;
@@ -839,9 +849,10 @@
s = APREQ_RUN_PARSER(ctx->hdr_parser, env, ctx->info, bb);
- if (s != APR_SUCCESS)
+ if (s != APR_SUCCESS) {
+ APREQ_BRIGADE_SETASIDE(bb, pool);
return (s == APR_EOF) ? APR_SUCCESS : s;
-
+ }
ctx->status = MFD_POST_HEADER;
}
/* fall through */
@@ -867,14 +878,18 @@
apr_bucket *e;
switch (brigade_start_string(bb, ctx->bdry + 2)) {
+
case APR_INCOMPLETE:
+ APREQ_BRIGADE_SETASIDE(bb, pool);
return APR_INCOMPLETE;
+
case APR_SUCCESS:
/* part has no body- return CRLF to front */
e = apr_bucket_transient_create(CRLF, 2,
ctx->bb->bucket_alloc);
APR_BRIGADE_INSERT_HEAD(bb,e);
break;
+
default:
; /* has body, ok */
}
@@ -918,18 +933,21 @@
case MFD_PARAM:
{
- apr_status_t s = split_on_bdry(ctx->bb, bb,
- ctx->pattern, ctx->bdry);
- apr_bucket *e;
apreq_param_t *param;
apreq_value_t *v;
const char *name;
apr_size_t len;
apr_off_t off;
+ apr_bucket *e;
+ apr_status_t s;
+
+ s = split_on_bdry(ctx->bb, bb, ctx->pattern, ctx->bdry);
switch (s) {
case APR_INCOMPLETE:
+ APREQ_BRIGADE_SETASIDE(bb, pool);
+ APREQ_BRIGADE_SETASIDE(ctx->bb,pool);
return s;
case APR_SUCCESS:
@@ -986,13 +1004,14 @@
if (s != APR_INCOMPLETE && s != APR_SUCCESS)
return s;
}
+ APREQ_BRIGADE_SETASIDE(ctx->bb, pool);
+ APREQ_BRIGADE_SETASIDE(bb, pool);
s = apreq_brigade_concat(env, param->bb, ctx->bb);
return (s == APR_SUCCESS) ? APR_INCOMPLETE : s;
case APR_SUCCESS:
if (parser->hook) {
- apr_bucket *eos =
- apr_bucket_eos_create(ctx->bb->bucket_alloc);
+ apr_bucket *eos =
apr_bucket_eos_create(bb->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->bb, eos);
s = APREQ_RUN_HOOK(parser->hook, env, param, ctx->bb);
apr_bucket_delete(eos);
@@ -1000,6 +1019,7 @@
return s;
}
+ APREQ_BRIGADE_SETASIDE(ctx->bb, pool);
param->v.status = apreq_brigade_concat(env,
param->bb, ctx->bb);
1.13 +2 -2 httpd-apreq-2/t/parsers.c
Index: parsers.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/parsers.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- parsers.c 10 Jun 2004 00:33:44 -0000 1.12
+++ parsers.c 14 Jun 2004 02:19:58 -0000 1.13
@@ -83,7 +83,7 @@
CuAssertPtrNotNull(tc, req);
CuAssertStrEquals(tc, req->env, apreq_env_content_type(req->env));
- for (j = 0; j < strlen(form_data); ++j) {
+ for (j = 0; j <= strlen(form_data); ++j) {
apr_bucket *e = apr_bucket_immortal_create(form_data,
strlen(form_data),
bb->bucket_alloc);
@@ -103,7 +103,7 @@
rv = apreq_parse_request(req,bb);
CuAssertIntEquals(tc, APR_INCOMPLETE, rv);
- rv = apreq_parse_request(req, tail);
+ rv = apreq_parse_request(req, tail);
CuAssertIntEquals(tc, APR_SUCCESS, rv);
CuAssertPtrNotNull(tc, req->body);
CuAssertIntEquals(tc, 2, apr_table_elts(req->body)->nelts);