1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24 #include "curlcheck.h"
25
26 #include "tool_cfgable.h"
27 #include "tool_doswin.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "memdebug.h" /* LAST include file */
34
unit_setup(void)35 static CURLcode unit_setup(void)
36 {
37 return CURLE_OK;
38 }
39
unit_stop(void)40 static void unit_stop(void)
41 {
42
43 }
44
45 #if defined(_WIN32) || defined(MSDOS)
46
getflagstr(int flags)47 static char *getflagstr(int flags)
48 {
49 char *buf = malloc(256);
50 if(buf) {
51 msnprintf(buf, 256, "%s,%s",
52 ((flags & SANITIZE_ALLOW_PATH) ?
53 "SANITIZE_ALLOW_PATH" : ""),
54 ((flags & SANITIZE_ALLOW_RESERVED) ?
55 "SANITIZE_ALLOW_RESERVED" : ""));
56 }
57 return buf;
58 }
59
getcurlcodestr(int cc)60 static char *getcurlcodestr(int cc)
61 {
62 char *buf = malloc(256);
63 if(buf) {
64 msnprintf(buf, 256, "%s (%d)",
65 (cc == SANITIZE_ERR_OK ? "SANITIZE_ERR_OK" :
66 cc == SANITIZE_ERR_BAD_ARGUMENT ? "SANITIZE_ERR_BAD_ARGUMENT" :
67 cc == SANITIZE_ERR_INVALID_PATH ? "SANITIZE_ERR_INVALID_PATH" :
68 cc == SANITIZE_ERR_OUT_OF_MEMORY ? "SANITIZE_ERR_OUT_OF_MEMORY":
69 "unexpected error code - add name"),
70 cc);
71 }
72 return buf;
73 }
74
75 struct data {
76 const char *input;
77 int flags;
78 const char *expected_output;
79 SANITIZEcode expected_result;
80 };
81
82 UNITTEST_START
83 { /* START sanitize_file_name */
84 struct data data[] = {
85 { "", 0,
86 "", SANITIZE_ERR_OK
87 },
88 { "normal filename", 0,
89 "normal filename", SANITIZE_ERR_OK
90 },
91 { "control\tchar", 0,
92 "control_char", SANITIZE_ERR_OK
93 },
94 { "banned*char", 0,
95 "banned_char", SANITIZE_ERR_OK
96 },
97 { "f:foo", 0,
98 "f_foo", SANITIZE_ERR_OK
99 },
100 { "f:foo", SANITIZE_ALLOW_PATH,
101 "f:foo", SANITIZE_ERR_OK
102 },
103 { "f:\\foo", 0,
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 #ifndef MSDOS
116 { "\\\\?\\C:\\foo", SANITIZE_ALLOW_PATH,
117 "\\\\?\\C:\\foo", SANITIZE_ERR_OK
118 },
119 { "\\\\?\\C:\\foo", 0,
120 "____C__foo", SANITIZE_ERR_OK
121 },
122 #endif
123 { "foo:bar", 0,
124 "foo_bar", SANITIZE_ERR_OK
125 },
126 { "foo|<>/bar\\\":?*baz", 0,
127 "foo____bar_____baz", SANITIZE_ERR_OK
128 },
129 { "f:foo::$DATA", 0,
130 "f_foo__$DATA", SANITIZE_ERR_OK
131 },
132 { "con . air", 0,
133 "con _ air", SANITIZE_ERR_OK
134 },
135 { "con.air", 0,
136 "con_air", SANITIZE_ERR_OK
137 },
138 { "con:/x", 0,
139 "con__x", SANITIZE_ERR_OK
140 },
141 { "file . . . . .. .", 0,
142 "file", SANITIZE_ERR_OK
143 },
144 { "foo . . ? . . ", 0,
145 "foo . . _", SANITIZE_ERR_OK
146 },
147 { "com1", 0,
148 "_com1", SANITIZE_ERR_OK
149 },
150 { "com1", SANITIZE_ALLOW_RESERVED,
151 "com1", SANITIZE_ERR_OK
152 },
153 { "f:\\com1", 0,
154 "f__com1", SANITIZE_ERR_OK
155 },
156 { "f:\\com1", SANITIZE_ALLOW_PATH,
157 "f:\\_com1", SANITIZE_ERR_OK
158 },
159 { "f:\\com1", SANITIZE_ALLOW_RESERVED,
160 "f__com1", SANITIZE_ERR_OK
161 },
162 { "f:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_PATH,
163 "f:\\com1", SANITIZE_ERR_OK
164 },
165 { "com1:\\com1", SANITIZE_ALLOW_PATH,
166 "_com1:\\_com1", SANITIZE_ERR_OK
167 },
168 { "com1:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_PATH,
169 "com1:\\com1", SANITIZE_ERR_OK
170 },
171 { "com1:\\com1", SANITIZE_ALLOW_RESERVED,
172 "com1__com1", SANITIZE_ERR_OK
173 },
174 #ifndef MSDOS
175 { "\\com1", SANITIZE_ALLOW_PATH,
176 "\\_com1", SANITIZE_ERR_OK
177 },
178 { "\\\\com1", SANITIZE_ALLOW_PATH,
179 "\\\\com1", SANITIZE_ERR_OK
180 },
181 { "\\\\?\\C:\\com1", SANITIZE_ALLOW_PATH,
182 "\\\\?\\C:\\com1", SANITIZE_ERR_OK
183 },
184 #endif
185 { "CoM1", 0,
186 "_CoM1", SANITIZE_ERR_OK
187 },
188 { "CoM1", SANITIZE_ALLOW_RESERVED,
189 "CoM1", SANITIZE_ERR_OK
190 },
191 { "COM56", 0,
192 "COM56", SANITIZE_ERR_OK
193 },
194 /* At the moment we expect a maximum path length of 259. I assume MS-DOS
195 has variable max path lengths depending on compiler that are shorter
196 so currently these "good" truncate tests will not run on MS-DOS */
197 { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
198 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
199 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
200 "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
201 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
202 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
203 0,
204 NULL, SANITIZE_ERR_INVALID_PATH
205 },
206 { NULL, 0,
207 NULL, SANITIZE_ERR_BAD_ARGUMENT
208 },
209 };
210
211 size_t i;
212
213 for(i = 0; i < sizeof(data) / sizeof(data[0]); ++i) {
214 char *output = NULL;
215 char *flagstr = NULL;
216 char *received_ccstr = NULL;
217 char *expected_ccstr = NULL;
218 SANITIZEcode res;
219
220 res = sanitize_file_name(&output, data[i].input, data[i].flags);
221
222 if(res == data[i].expected_result &&
223 ((!output && !data[i].expected_output) ||
224 (output && data[i].expected_output &&
225 !strcmp(output, data[i].expected_output)))) { /* OK */
226 free(output);
227 continue;
228 }
229
230 flagstr = getflagstr(data[i].flags);
231 abort_unless(flagstr, "out of memory");
232 received_ccstr = getcurlcodestr(res);
233 abort_unless(received_ccstr, "out of memory");
234 expected_ccstr = getcurlcodestr(data[i].expected_result);
235 abort_unless(expected_ccstr, "out of memory");
236
237 unitfail++;
238 fprintf(stderr, "\n"
239 "%s:%d sanitize_file_name failed.\n"
240 "input: %s\n"
241 "flags: %s\n"
242 "output: %s\n"
243 "result: %s\n"
244 "expected output: %s\n"
245 "expected result: %s\n",
246 __FILE__, __LINE__,
247 data[i].input,
248 flagstr,
249 (output ? output : "(null)"),
250 received_ccstr,
251 (data[i].expected_output ? data[i].expected_output : "(null)"),
252 expected_ccstr);
253
254 free(output);
255 free(flagstr);
256 free(received_ccstr);
257 free(expected_ccstr);
258 }
259 } /* END sanitize_file_name */
260
261 #else
262 UNITTEST_START
263 {
264 fprintf(stderr, "Skipped test not for this platform\n");
265 }
266 #endif /* _WIN32 || MSDOS */
267
268 UNITTEST_STOP
269