tool_doswin: increase allowable length of path sanitizer
No binary (build failed)
—
(log yok)
| @@ -88,8 +88,11 @@ SANITIZE_ALLOW_PATH: Allow path separators and colons. | |
| Without this flag path separators and colons are sanitized. | |
| SANITIZE_ALLOW_RESERVED: Allow reserved device names. | |
| - | Without this flag a reserved device name is renamed (COM1 => _COM1) unless it |
| - | is in a UNC prefixed path. |
| + | Without this flag a reserved device name is renamed (COM1 => _COM1). |
| + | |
| + | To fully block reserved device names requires not passing either flag. Some |
| + | less common path styles are allowed to use reserved device names. For example, |
| + | a "\\" prefixed path may use reserved device names if paths are allowed. |
| Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. | |
| Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL. | |
| @@ -110,15 +113,13 @@ SANITIZEcode sanitize_file_name(char ** const sanitized, const char *file_name, | |
| if(!file_name) | |
| return SANITIZE_ERR_BAD_ARGUMENT; | |
| - | if(flags & SANITIZE_ALLOW_PATH) { |
| - | #ifndef MSDOS |
| - | if(file_name[0] == '\\' && file_name[1] == '\\') |
| - | /* UNC prefixed path \\ (eg \\?\C:\foo) */ |
| - | max_sanitized_len = 32767 - 1; |
| - | else |
| + | if(flags & SANITIZE_ALLOW_PATH) |
| + | #ifdef MSDOS |
| + | max_sanitized_len = PATH_MAX - 1; |
| + | #else |
| + | /* Windows extended-length path max */ |
| + | max_sanitized_len = 32767 - 1; |
| #endif | |
| - | max_sanitized_len = PATH_MAX - 1; |
| - | } |
| else | |
| /* The maximum length of a filename. FILENAME_MAX is often the same as | |
| PATH_MAX, in other words it is 260 and does not discount the path | |
| @@ -135,7 +136,7 @@ SANITIZEcode sanitize_file_name(char ** const sanitized, const char *file_name, | |
| #ifndef MSDOS | |
| if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4)) | |
| - | /* Skip the literal path prefix \\?\ */ |
| + | /* Skip the literal-path prefix \\?\ */ |
| p = target + 4; | |
| else | |
| #endif | |
| @@ -438,20 +439,18 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, | |
| /* We could have a file whose name is a device on MS-DOS. Trying to | |
| * retrieve such a file would fail at best and wedge us at worst. We need | |
| * to rename such files. */ | |
| - | char *p, *base; |
| - | char fname[PATH_MAX]; |
| + | char *p, *base, *buffer; |
| #ifdef MSDOS | |
| struct_stat st_buf; | |
| #endif | |
| - | size_t len; |
| + | size_t len, bufsize; |
| if(!sanitized || !file_name) | |
| return SANITIZE_ERR_BAD_ARGUMENT; | |
| *sanitized = NULL; | |
| - | len = strlen(file_name); |
| - | /* Ignore UNC prefixed paths, they are allowed to contain a reserved name. */ |
| + | /* Ignore "\\" prefixed paths, they are allowed to use reserved names. */ |
| #ifndef MSDOS | |
| if((flags & SANITIZE_ALLOW_PATH) && | |
| file_name[0] == '\\' && file_name[1] == '\\') { | |
| @@ -462,19 +461,25 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, | |
| } | |
| #endif | |
| - | if(len > PATH_MAX - 1) |
| - | return SANITIZE_ERR_INVALID_PATH; |
| + | /* The buffer contains two extra bytes to allow for path expansion that |
| + | occurs if reserved name(s) need an underscore prepended. */ |
| + | len = strlen(file_name); |
| + | bufsize = len + 2 + 1; |
| + | |
| + | buffer = curlx_malloc(bufsize); |
| + | if(!buffer) |
| + | return SANITIZE_ERR_OUT_OF_MEMORY; |
| + | |
| + | memcpy(buffer, file_name, len + 1); |
| - | memcpy(fname, file_name, len); |
| - | fname[len] = '\0'; |
| - | base = basename(fname); |
| + | base = basename(buffer); |
| /* Rename reserved device names that are known to be accessible without \\.\ | |
| Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS | |
| https://web.archive.org/web/20160314141551/support.microsoft.com/en-us/kb/74496 | |
| https://learn.microsoft.com/windows/win32/fileio/naming-a-file | |
| */ | |
| - | for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) { |
| + | for(p = buffer; p; p = (p == buffer && buffer != base ? base : NULL)) { |
| size_t p_len; | |
| int x = (curl_strnequal(p, "CON", 3) || | |
| curl_strnequal(p, "PRN", 3) || | |
| @@ -511,15 +516,18 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, | |
| p_len = strlen(p); | |
| /* Prepend a '_' */ | |
| - | if(strlen(fname) == PATH_MAX - 1) |
| + | if(len == bufsize - 1) { |
| + | curlx_free(buffer); |
| return SANITIZE_ERR_INVALID_PATH; | |
| + | } |
| memmove(p + 1, p, p_len + 1); | |
| p[0] = '_'; | |
| ++p_len; | |
| + | ++len; |
| - | /* if fname was just modified then the basename pointer must be updated */ |
| - | if(p == fname) |
| - | base = basename(fname); |
| + | /* the basename pointer must be updated since the path has expanded */ |
| + | if(p == buffer) |
| + | base = basename(buffer); |
| } | |
| /* This is the legacy portion from rename_if_dos_device_name that checks for | |
| @@ -534,16 +542,19 @@ static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, | |
| /* Prepend a '_' */ | |
| size_t blen = strlen(base); | |
| if(blen) { | |
| - | if(strlen(fname) >= PATH_MAX - 1) |
| + | if(len == bufsize - 1) { |
| + | curlx_free(buffer); |
| return SANITIZE_ERR_INVALID_PATH; | |
| + | } |
| memmove(base + 1, base, blen + 1); | |
| base[0] = '_'; | |
| + | ++len; |
| } | |
| } | |
| #endif | |
| - | *sanitized = curlx_strdup(fname); |
| - | return *sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY; |
| + | *sanitized = buffer; |
| + | return SANITIZE_ERR_OK; |
| } | |
| #ifdef __DJGPP__ | |
| @@ -178,9 +178,6 @@ static CURLcode test_tool1604(const char *arg) | |
| { "COM56", 0, | |
| "COM56", SANITIZE_ERR_OK | |
| }, | |
| - | /* At the moment we expect a maximum path length of 259. I assume MS-DOS |
| - | has variable max path lengths depending on compiler that are shorter |
| - | so currently these "good" truncate tests will not run on MS-DOS */ |
| { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | |
| "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" | |
| "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" | |