Package: xdelta3 / 3.0.0.dfsg-1+deb7u1

CVE-2014-9765.diff Patch series | download
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
Description: CVE-2014-9765: buffer overflow in main_get_appheader
Origin: upstream, https://github.com/jmacd/xdelta/commit/969e65d3a5d70442f5bafd726bcef47a0b48edd8
Bug-Debian: https://bugs.debian.org/814067
Forwarded: not-needed
Author: Josh MacDonald <josh.macdonald@gmail.com>
Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
Last-Update: 2016-02-10
Applied-Upstream: 3.0.9

---

--- a/xdelta3-test.h
+++ b/xdelta3-test.h
@@ -150,7 +150,7 @@ static int do_cmd (xd3_stream *stream, c
 	{
 	  stream->msg = "abnormal command termination";
 	}
-      return XD3_INTERNAL;
+      return ret;
     }
   return 0;
 }
@@ -421,12 +421,12 @@ compare_files (xd3_stream *stream, const
 }
 
 static int
-test_save_copy (const char *origname)
+test_copy_to (const char *from, const char *to)
 {
   char buf[TESTBUFSIZE];
   int ret;
 
-  sprintf (buf, "cp -f %s %s", origname, TEST_COPY_FILE);
+  snprintf (buf, TESTBUFSIZE, "cp -f %s %s", from, to);
 
   if ((ret = system (buf)) != 0)
     {
@@ -437,6 +437,12 @@ test_save_copy (const char *origname)
 }
 
 static int
+test_save_copy (const char *origname)
+{
+  return test_copy_to(origname, TEST_COPY_FILE);
+}
+
+static int
 test_file_size (const char* file, xoff_t *size)
 {
   struct stat sbuf;
@@ -2342,6 +2348,76 @@ test_no_output (xd3_stream *stream, int
   return 0;
 }
 
+/* This tests that the default appheader works */
+static int
+test_appheader (xd3_stream *stream, int ignore)
+{
+  int i;
+  int ret;
+  char buf[TESTBUFSIZE];
+  char bogus[TESTBUFSIZE];
+  xoff_t ssize, tsize;
+  test_setup ();
+
+  if ((ret = test_make_inputs (stream, &ssize, &tsize))) { return ret; }
+
+  snprintf (buf, TESTBUFSIZE, "%s -q -f -e -s %s %s %s", program_name,
+		 TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE);
+  if ((ret = do_cmd (stream, buf))) { return ret; }
+
+  if ((ret = test_copy_to (program_name, TEST_RECON2_FILE))) { return ret; }
+
+  snprintf (buf, TESTBUFSIZE, "chmod 0700 %s", TEST_RECON2_FILE);
+  if ((ret = do_cmd (stream, buf))) { return ret; }
+
+  if ((ret = test_save_copy (TEST_TARGET_FILE))) { return ret; }
+  if ((ret = test_copy_to (TEST_SOURCE_FILE, TEST_TARGET_FILE))) { return ret; }
+
+  if ((ret = compare_files (stream, TEST_TARGET_FILE, TEST_COPY_FILE)) == 0)
+    {
+      return XD3_INVALID;  // I.e., files are different!
+    }
+
+  // Test that the target file is restored.
+  snprintf (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)",
+		 TEST_RECON2_FILE,
+		 TEST_DELTA_FILE);
+  if ((ret = do_cmd (stream, buf))) { return ret; }
+
+  if ((ret = compare_files (stream, TEST_TARGET_FILE, TEST_COPY_FILE)) != 0)
+    {
+      return ret;
+    }
+
+  // Test a malicious string w/ entries > 4 in the appheader by having
+  // the encoder write it:
+  for (i = 0; i < TESTBUFSIZE / 4; ++i)
+    {
+      bogus[2*i] = 'G';
+      bogus[2*i+1] = '/';
+    }
+  bogus[TESTBUFSIZE/2-1] = 0;
+
+  snprintf (buf, TESTBUFSIZE,
+		 "%s -q -f -A=%s -e -s %s %s %s", program_name, bogus,
+		 TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE);
+  if ((ret = do_cmd (stream, buf))) { return ret; }
+  // Then read it:
+  snprintf (buf, TESTBUFSIZE, "(cd /tmp && %s -q -f -d %s)",
+		 TEST_RECON2_FILE,
+		 TEST_DELTA_FILE);
+  if ((ret = do_cmd (stream, buf)) == 0) 
+    { 
+      return XD3_INVALID;  // Impossible
+    }
+  if (!WIFEXITED(ret))
+    {
+      return XD3_INVALID;  // Must have crashed!
+    }
+
+  return 0;
+}
+
 /***********************************************************************
  Source identical optimization
  ***********************************************************************/
@@ -2839,6 +2915,7 @@ xd3_selftest (void)
   DO_TEST (force_behavior, 0, 0);
   DO_TEST (stdout_behavior, 0, 0);
   DO_TEST (no_output, 0, 0);
+  DO_TEST (appheader, 0, 0);
   DO_TEST (command_line_arguments, 0, 0);
 
 #if EXTERNAL_COMPRESSION
--- a/xdelta3-main.h
+++ b/xdelta3-main.h
@@ -2826,14 +2826,15 @@ main_get_appheader (xd3_stream *stream,
 
   if (appheadsz > 0)
     {
+      const int kMaxArgs = 4;
       char *start = (char*)apphead;
       char *slash;
       int   place = 0;
-      char *parsed[4];
+      char *parsed[kMaxArgs];
 
       memset (parsed, 0, sizeof (parsed));
 
-      while ((slash = strchr (start, '/')) != NULL)
+      while ((slash = strchr (start, '/')) != NULL && place < (kMaxArgs-1))
 	{
 	  *slash = 0;
 	  parsed[place++] = start;