mirror of
https://github.com/curl/curl.git
synced 2026-04-15 02:31:40 +03:00
tool_doswin: increase allowable length of path sanitizer
- Use 32767-1 instead of PATH_MAX-1 (260-1) as the maximum allowable length of a path in Windows. Prior to this change the path sanitizer in Windows used 32767-1 as the maximum length only for paths that had the "\\" prefix like "\\?\longpath". Since then we added some workarounds to open longer paths without "\\?\" prefix by normalizing the path and adding that prefix, and the sanitizer is called before the prefix is added. Bug: https://github.com/curl/curl/issues/20044 Reported-by: Viktor Szakats Closes https://github.com/curl/curl/pull/20046
This commit is contained in:
parent
52ac8104e1
commit
1068d048ec
2 changed files with 40 additions and 32 deletions
|
|
@ -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;
|
||||
|
||||
memcpy(fname, file_name, len);
|
||||
fname[len] = '\0';
|
||||
base = basename(fname);
|
||||
buffer = curlx_malloc(bufsize);
|
||||
if(!buffer)
|
||||
return SANITIZE_ERR_OUT_OF_MEMORY;
|
||||
|
||||
memcpy(buffer, file_name, len + 1);
|
||||
|
||||
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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue