PerlDancer / Dancer2

Perl Dancer Next Generation (rewrite of Perl Dancer)
http://perldancer.org/
Other
537 stars 272 forks source link

Cookie parsing bug #1701

Open nfg opened 8 months ago

nfg commented 8 months ago

Hey!

I found a bunch of warnings for a service at work built on Dancer2. When I did some investigating, I figured out it was because we were setting some values in the cookies that aren't handled properly when the browser hits the site again.

#!/usr/bin/env perl

use Dancer2;
use Data::Printer;

my $cookie_value = "hmm; this & that";

any '/' => sub {
    my $cookie = cookie("test");
    if ($cookie) {
        my @values = $cookie->value();
        p @values;
    }
    cookie("test", $cookie_value, expires => '+30m');
    send_as plain => "NOM NOM NOM";
};

dance();

The cookie header from curl looks like

< Set-Cookie: test=hmm%3b%20this%20%26%20that; Expires=Tue, 31-Oct-2023 01:33:10 GMT; HttpOnly; Path=/

Awesome. But when I hit it in the browser, it dumps out these values:

[
    [0] "hmm; this ",
    [1] " that"
]

That's with HTTP::XSCookies installed. If I take that out, I get

< Set-Cookie: test=hmm%3B%20this%20%26%20that; Path=/; Expires=Tue, 31-Oct-2023 01:28:47 GMT; HttpOnly

and

[
    [0] "hmm",
    [1] " this ",
    [2] " that"
]

I think the problem is in Dancer2::Core::Request::_build_cookies. It can split the cookie values:

    # convert to objects
    while (my ($name, $value) = each %{$cookies}) {
        $cookies->{$name} = Dancer2::Core::Cookie->new(
            name  => $name,
            # HTTP::XSCookies v0.17+ will do the split and return an arrayref
            value => (is_arrayref($value) ? $value : [split(/[&;]/, $value)])
        );
    }

I have no idea why the split behaves differently between HTTP::XSCookies and Cookie::Baker. As far as I can tell, the parsed cookie value is identical.