summaryrefslogtreecommitdiff
path: root/core/perl/cgi-cr-escaping.diff
blob: 51adf7231a4299ae09e1b61b8fc5abd7d8fe4167 (plain)
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
68
69
70
71
72
73
74
75
From 18b607e4544c0cffc85207a8f9901ba37ac917d9 Mon Sep 17 00:00:00 2001
From: Ryo Anazawa <anazawa@cpan.org>
Date: Wed, 14 Nov 2012 09:47:32 +0900
Subject: CR escaping for P3P and Set-Cookie headers

Bug: https://github.com/markstos/CGI.pm/pull/23
Bug-Debian: http://bugs.debian.org/693420
Origin: https://github.com/markstos/CGI.pm/commit/cb39938b45206093a363e36fd104e4a0f26deecb
Patch-Name: fixes/cgi-cr-escaping.diff
---
 cpan/CGI/lib/CGI.pm  |   24 ++++++++++++------------
 cpan/CGI/t/headers.t |    6 ++++++
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/cpan/CGI/lib/CGI.pm b/cpan/CGI/lib/CGI.pm
index 1a52c70..c70e9c1 100644
--- a/cpan/CGI/lib/CGI.pm
+++ b/cpan/CGI/lib/CGI.pm
@@ -1550,8 +1550,17 @@ sub header {
                             '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
@@ -1595,18 +1604,9 @@ sub header {
 
     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)
diff --git a/cpan/CGI/t/headers.t b/cpan/CGI/t/headers.t
index 661b74b..4b4922c 100644
--- a/cpan/CGI/t/headers.t
+++ b/cpan/CGI/t/headers.t
@@ -22,6 +22,12 @@ like($@,qr/contains a newline/,'invalid header blows up');
 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');