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