I just upgraded to the newest Apache2/mod_perl2, which needed
libapreq2-2.05-dev for Apache2::Request. Apache 2.0.54, mod_perl 2.0.0, perl
5.8.6.
The following statement died with an error about err_headers_out:
Apache2::Cookie->new($r, name => 'blah', value => $sid, expires => '+1D',
path => '/path')->bake();
Fine, checked the code, found that bake now wants $r (strange to require it
two places, but OK, it's 'dev'):
Apache2::Cookie->new($r, name => 'blah', value => $sid, expires => '+1D',
path => '/path')->bake($r);
But now it's outputting a cookie with path '+1D' (and everything else
correct).
if I call path() and expires() separately, it's OK.
I put some trace prints in Apache2::Cookie::new (this is the code that sets
expires and path, name and value are done explicitly):
while(my ($k, $v) = each %attrs) {
$k =~ s/^-//;
print STDERR "setting '$k' to '$v'\n";
print STDERR "pre: ".$cookie->as_string()."\n";
$cookie->$k($v);
print STDERR "post: ".$cookie->as_string()."\n";
}
return $cookie;
Oddly, the 'path' value is corrupt before expires() is even called. I smell
rodent and look for the C code for path(), finding it in Cookie.xs:
--- begin function ---
char *
path(obj, val=NULL)
APR::Request::Cookie obj
char * val
PREINIT:
/*nada*/
CODE:
RETVAL = (char *) obj->path;
if (items > 1) {
obj->path = (char *) val;
}
OUTPUT:
RETVAL
--- end function ---
C programmers will probably see what's wrong here: copying a volatile pointer
(aliasing bug). The char* comes from SvPV_nolen(), which points into the SV,
in this case $v from the 'each'. When $v changes, so will the value of path.
When $v goes out of scope and its PV gets freed, 'val' will be overwritten by
whatever uses the space.
The same problem occurs in the other generated char* functions, e.g. domain,
port, comment, etc.
Should the passed-in strings could be allocated space from the Apache pool
like name and value? I figure someone else is better positioned to make a
clean fix, but if not I can look into writing up a patch.
--
Dave
Isa. 40:31