1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "curlcheck.h"
23 
24 #include "tool_cfgable.h"
25 #include "tool_doswin.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "memdebug.h" /* LAST include file */
32 
unit_setup(void)33 static CURLcode unit_setup(void)
34 {
35   return CURLE_OK;
36 }
37 
unit_stop(void)38 static void unit_stop(void)
39 {
40 
41 }
42 
43 #if defined(MSDOS) || defined(WIN32)
44 
getflagstr(int flags)45 static char *getflagstr(int flags)
46 {
47   char *buf = malloc(256);
48   if(buf) {
49     msnprintf(buf, 256, "%s,%s,%s,%s",
50               ((flags & SANITIZE_ALLOW_COLONS) ?
51                "SANITIZE_ALLOW_COLONS" : ""),
52               ((flags & SANITIZE_ALLOW_PATH) ?
53                "SANITIZE_ALLOW_PATH" : ""),
54               ((flags & SANITIZE_ALLOW_RESERVED) ?
55                "SANITIZE_ALLOW_RESERVED" : ""),
56               ((flags & SANITIZE_ALLOW_TRUNCATE) ?
57                "SANITIZE_ALLOW_TRUNCATE" : ""));
58   }
59   return buf;
60 }
61 
getcurlcodestr(int cc)62 static char *getcurlcodestr(int cc)
63 {
64   char *buf = malloc(256);
65   if(buf) {
66     msnprintf(buf, 256, "%s (%d)",
67               (cc == SANITIZE_ERR_OK ? "SANITIZE_ERR_OK" :
68                cc == SANITIZE_ERR_BAD_ARGUMENT ? "SANITIZE_ERR_BAD_ARGUMENT" :
69                cc == SANITIZE_ERR_INVALID_PATH ? "SANITIZE_ERR_INVALID_PATH" :
70                cc == SANITIZE_ERR_OUT_OF_MEMORY ? "SANITIZE_ERR_OUT_OF_MEMORY":
71                "unexpected error code - add name"),
72               cc);
73   }
74   return buf;
75 }
76 
77 struct data {
78   const char *input;
79   int flags;
80   const char *expected_output;
81   SANITIZEcode expected_result;
82 };
83 
84 UNITTEST_START
85 
86 { /* START sanitize_file_name */
87   struct data data[] = {
88     { "", 0,
89       "", SANITIZE_ERR_OK
90     },
91     { "normal filename", 0,
92       "normal filename", SANITIZE_ERR_OK
93     },
94     { "control\tchar", 0,
95       "control_char", SANITIZE_ERR_OK
96     },
97     { "banned*char", 0,
98       "banned_char", SANITIZE_ERR_OK
99     },
100     { "f:foo", 0,
101       "f_foo", SANITIZE_ERR_OK
102     },
103     { "f:foo", SANITIZE_ALLOW_COLONS,
104       "f:foo", SANITIZE_ERR_OK
105     },
106     { "f:foo", SANITIZE_ALLOW_PATH,
107       "f:foo", SANITIZE_ERR_OK
108     },
109     { "f:\\foo", 0,
110       "f__foo", SANITIZE_ERR_OK
111     },
112     { "f:\\foo", SANITIZE_ALLOW_PATH,
113       "f:\\foo", SANITIZE_ERR_OK
114     },
115     { "f:/foo", 0,
116       "f__foo", SANITIZE_ERR_OK
117     },
118     { "f:/foo", SANITIZE_ALLOW_PATH,
119       "f:/foo", SANITIZE_ERR_OK
120     },
121 #ifndef MSDOS
122     { "\\\\?\\C:\\foo", SANITIZE_ALLOW_PATH,
123       "\\\\?\\C:\\foo", SANITIZE_ERR_OK
124     },
125     { "\\\\?\\C:\\foo", 0,
126       "____C__foo", SANITIZE_ERR_OK
127     },
128 #endif
129     { "foo:bar", 0,
130       "foo_bar", SANITIZE_ERR_OK
131     },
132     { "foo|<>/bar\\\":?*baz", 0,
133       "foo____bar_____baz", SANITIZE_ERR_OK
134     },
135     { "f:foo::$DATA", 0,
136       "f_foo__$DATA", SANITIZE_ERR_OK
137     },
138     { "con . air", 0,
139       "con _ air", SANITIZE_ERR_OK
140     },
141     { "con.air", 0,
142       "con_air", SANITIZE_ERR_OK
143     },
144     { "con:/x", 0,
145       "con__x", SANITIZE_ERR_OK
146     },
147     { "file . . . .  ..  .", 0,
148       "file", SANITIZE_ERR_OK
149     },
150     { "foo . . ? . . ", 0,
151       "foo . . _", SANITIZE_ERR_OK
152     },
153     { "com1", 0,
154       "_com1", SANITIZE_ERR_OK
155     },
156     { "com1", SANITIZE_ALLOW_RESERVED,
157       "com1", SANITIZE_ERR_OK
158     },
159     { "f:\\com1", 0,
160       "f__com1", SANITIZE_ERR_OK
161     },
162     { "f:\\com1", SANITIZE_ALLOW_PATH,
163       "f:\\_com1", SANITIZE_ERR_OK
164     },
165     { "f:\\com1", SANITIZE_ALLOW_RESERVED,
166       "f__com1", SANITIZE_ERR_OK
167     },
168     { "f:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_COLONS,
169       "f:_com1", SANITIZE_ERR_OK
170     },
171     { "f:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_PATH,
172       "f:\\com1", SANITIZE_ERR_OK
173     },
174     { "com1:\\com1", SANITIZE_ALLOW_PATH,
175       "_com1:\\_com1", SANITIZE_ERR_OK
176     },
177     { "com1:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_PATH,
178       "com1:\\com1", SANITIZE_ERR_OK
179     },
180     { "com1:\\com1", SANITIZE_ALLOW_RESERVED,
181       "com1__com1", SANITIZE_ERR_OK
182     },
183 #ifndef MSDOS
184     { "\\com1", SANITIZE_ALLOW_PATH,
185       "\\_com1", SANITIZE_ERR_OK
186     },
187     { "\\\\com1", SANITIZE_ALLOW_PATH,
188       "\\\\com1", SANITIZE_ERR_OK
189     },
190     { "\\\\?\\C:\\com1", SANITIZE_ALLOW_PATH,
191       "\\\\?\\C:\\com1", SANITIZE_ERR_OK
192     },
193 #endif
194     { "CoM1", 0,
195       "_CoM1", SANITIZE_ERR_OK
196     },
197     { "CoM1", SANITIZE_ALLOW_RESERVED,
198       "CoM1", SANITIZE_ERR_OK
199     },
200     { "COM56", 0,
201       "COM56", SANITIZE_ERR_OK
202     },
203     /* At the moment we expect a maximum path length of 259. I assume MSDOS
204        has variable max path lengths depending on compiler that are shorter
205        so currently these "good" truncate tests won't run on MSDOS */
206 #ifndef MSDOS
207     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
208       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
209       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
210       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
211       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
212       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
213         SANITIZE_ALLOW_TRUNCATE,
214       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
215       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
216       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
217       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
218       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
219       "FFFFF", SANITIZE_ERR_OK
220     },
221     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
222       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
223       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
224       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
225       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
226       "FFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
227         SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
228       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
229       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
230       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
231       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
232       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
233       "FFF\\FFFFF", SANITIZE_ERR_OK
234     },
235     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
236       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
237       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
238       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
239       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
240       "FFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
241         SANITIZE_ALLOW_TRUNCATE,
242       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
243       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
244       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
245       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
246       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
247       "FFF_F", SANITIZE_ERR_OK
248     },
249 #endif /* !MSDOS */
250     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
251       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
252       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
253       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
254       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
255       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
256         0,
257       NULL, SANITIZE_ERR_INVALID_PATH
258     },
259     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
260       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
261       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
262       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
263       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
264       "FFFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
265         SANITIZE_ALLOW_TRUNCATE,
266       NULL, SANITIZE_ERR_INVALID_PATH
267     },
268     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
269       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
270       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
271       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
272       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
273       "FFFFFFFFFFFFFFFFFFFFFFFFF\\FFFFFFFFFFFFFFFFFFFFFFFF",
274         SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
275       NULL, SANITIZE_ERR_INVALID_PATH
276     },
277     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
278       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
279       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
280       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
281       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
282       "FFF\\FFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFF",
283         SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
284       NULL, SANITIZE_ERR_INVALID_PATH
285     },
286     { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
287       "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
288       "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
289       "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
290       "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
291       "FF\\F:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
292         SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
293       NULL, SANITIZE_ERR_INVALID_PATH
294     },
295     { NULL, 0,
296       NULL, SANITIZE_ERR_BAD_ARGUMENT
297     },
298   };
299 
300   size_t i;
301 
302   for(i = 0; i < sizeof(data) / sizeof(data[0]); ++i) {
303     char *output = NULL;
304     char *flagstr = NULL;
305     char *received_ccstr = NULL;
306     char *expected_ccstr = NULL;
307     SANITIZEcode res;
308 
309     res = sanitize_file_name(&output, data[i].input, data[i].flags);
310 
311     if(res == data[i].expected_result &&
312        ((!output && !data[i].expected_output) ||
313         (output && data[i].expected_output &&
314          !strcmp(output, data[i].expected_output)))) { /* OK */
315       free(output);
316       continue;
317     }
318 
319     flagstr = getflagstr(data[i].flags);
320     abort_unless(flagstr, "out of memory");
321     received_ccstr = getcurlcodestr(res);
322     abort_unless(received_ccstr, "out of memory");
323     expected_ccstr = getcurlcodestr(data[i].expected_result);
324     abort_unless(expected_ccstr, "out of memory");
325 
326     unitfail++;
327     fprintf(stderr, "\n"
328             "%s:%d sanitize_file_name failed.\n"
329             "input: %s\n"
330             "flags: %s\n"
331             "output: %s\n"
332             "result: %s\n"
333             "expected output: %s\n"
334             "expected result: %s\n",
335             __FILE__, __LINE__,
336             data[i].input,
337             flagstr,
338             (output ? output : "(null)"),
339             received_ccstr,
340             (data[i].expected_output ? data[i].expected_output : "(null)"),
341             expected_ccstr);
342 
343     free(output);
344     free(flagstr);
345     free(received_ccstr);
346     free(expected_ccstr);
347   }
348 } /* END sanitize_file_name */
349 
350 #else
351 UNITTEST_START
352 
353 {
354   fprintf(stderr, "Skipped test not for this platform\n");
355 }
356 #endif /* MSDOS || WIN32 */
357 
358 UNITTEST_STOP
359