aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch
blob: 195d3095066a82d091c19e725b6699936ba549de (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
dpkg: Security Advisory - CVE-2014-0471

commit a82651188476841d190c58693f95827d61959b51 upstream

Directory traversal vulnerability in the unpacking functionality in
dpkg before 1.15.9, 1.16.x before 1.16.13, and 1.17.x before 1.17.8
allows remote attackers to write arbitrary files via a crafted source
package, related to "C-style filename quoting."

Upstream-Status: Backport

Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
Signed-off-by: Wenzong Fan <wenzong.fan@windriver.com>
===================================================
diff -uarN dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm
--- dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm	2014-06-05 15:24:07.422446284 +0800
+++ dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm	2014-06-05 15:41:37.746446314 +0800
@@ -324,14 +324,53 @@
     return $line;
 }
 
-# Strip timestamp
-sub _strip_ts {
-    my $header = shift;
-
-    # Tab is the official separator, it's always used when
-    # filename contain spaces. Try it first, otherwise strip on space
-    # if there's no tab
-    $header =~ s/\s.*// unless ($header =~ s/\t.*//);
+my %ESCAPE = ((
+    'a' => "\a",
+    'b' => "\b",
+    'f' => "\f",
+    'n' => "\n",
+    'r' => "\r",
+    't' => "\t",
+    'v' => "\cK",
+    '\\' => '\\',
+    '"' => '"',
+), (
+    map { sprintf('%03o', $_) => chr($_) } (0..255)
+));
+
+sub _unescape {
+    my ($diff, $str) = @_;
+
+    if (exists $ESCAPE{$str}) {
+        return $ESCAPE{$str};
+    } else {
+        error(_g('diff %s patches file with unknown escape sequence \\%s'),
+              $diff, $str);
+    }
+}
+
+# Fetch the header filename ignoring the optional timestamp
+sub _fetch_filename {
+    my ($diff, $header) = @_;
+
+    # Strip any leading spaces.
+    $header =~ s/^\s+//;
+
+    # Is it a C-style string?
+    if ($header =~ m/^"/) {
+        $header =~ m/^"((?:[^\\"]|\\.)*)"/;
+        error(_g('diff %s patches file with unbalanced quote'), $diff)
+            unless defined $1;
+
+        $header = $1;
+        $header =~ s/\\([0-3][0-7]{2}|.)/_unescape($diff, $1)/eg;
+    } else {
+        # Tab is the official separator, it's always used when
+        # filename contain spaces. Try it first, otherwise strip on space
+        # if there's no tab
+        $header =~ s/\s.*// unless $header =~ s/\t.*//;
+    }
+
     return $header;
 }
 
@@ -400,7 +439,7 @@
 	unless(s/^--- //) {
 	    error(_g("expected ^--- in line %d of diff `%s'"), $., $diff);
 	}
-        $path{old} = $_ = _strip_ts($_);
+	$path{old} = $_ = _fetch_filename($diff, $_);
 	$fn{old} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/};
 	if (/\.dpkg-orig$/) {
 	    error(_g("diff `%s' patches file with name ending .dpkg-orig"), $diff);
@@ -412,7 +451,7 @@
 	unless (s/^\+\+\+ //) {
 	    error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.);
 	}
-        $path{new} = $_ = _strip_ts($_);
+	$path{new} = $_ = _fetch_filename($diff, $_);
 	$fn{new} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/};
 
 	unless (defined $fn{old} or defined $fn{new}) {