1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
From d5f9eaeea977edd24b3e6fdec7871ab254733ba4 Mon Sep 17 00:00:00 2001
From: Ryo Anazawa <anazawa@cpan.org>
Date: Wed, 14 Nov 2012 09:47:32 +0900
Subject: [PATCH] CR escaping for P3P and Set-Cookie headers
---
lib/CGI.pm | 24 ++++++++++++------------
t/headers.t | 6 ++++++
2 files changed, 18 insertions(+), 12 deletions(-)
--- a/lib/CGI.pm
+++ b/lib/CGI.pm
@@ -1549,8 +1549,17 @@
'EXPIRES','NPH','CHARSET',
'ATTACHMENT','P3P'],@p);
+ # Since $cookie and $p3p may be array references,
+ # we must stringify them before CR escaping is done.
+ my @cookie;
+ for (ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie) {
+ my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
+ push(@cookie,$cs) if defined $cs and $cs ne '';
+ }
+ $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
+
# CR escaping for values, per RFC 822
- for my $header ($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
+ for my $header ($type,$status,@cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
if (defined $header) {
# From RFC 822:
# Unfolding is accomplished by regarding CRLF immediately
@@ -1598,18 +1607,9 @@
push(@header,"Status: $status") if $status;
push(@header,"Window-Target: $target") if $target;
- if ($p3p) {
- $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
- push(@header,qq(P3P: policyref="/w3c/p3p.xml", CP="$p3p"));
- }
+ push(@header,"P3P: policyref=\"/w3c/p3p.xml\", CP=\"$p3p\"") if $p3p;
# push all the cookies -- there may be several
- if ($cookie) {
- my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie;
- for (@cookie) {
- my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
- push(@header,"Set-Cookie: $cs") if $cs ne '';
- }
- }
+ push(@header,map {"Set-Cookie: $_"} @cookie);
# if the user indicates an expiration time, then we need
# both an Expires and a Date header (so that the browser is
# uses OUR clock)
--- a/t/headers.t
+++ b/t/headers.t
@@ -22,6 +22,12 @@
like $cgi->header( -type => "text/html".$CGI::CRLF." evil: stuff " ),
qr#Content-Type: text/html evil: stuff#, 'known header, with leading and trailing whitespace on the continuation line';
+eval { $cgi->header( -p3p => ["foo".$CGI::CRLF."bar"] ) };
+like($@,qr/contains a newline/,'P3P header with CRLF embedded blows up');
+
+eval { $cgi->header( -cookie => ["foo".$CGI::CRLF."bar"] ) };
+like($@,qr/contains a newline/,'Set-Cookie header with CRLF embedded blows up');
+
eval { $cgi->header( -foobar => "text/html".$CGI::CRLF."evil: stuff" ) };
like($@,qr/contains a newline/,'unknown header with CRLF embedded blows up');
|