https://sourceware.org/bugzilla/show_bug.cgi?id=28897
Bug ID: 28897 Summary: bdf/bdfio.c does not properly detect "long paths" containing ".." Product: binutils Version: 2.37 Status: UNCONFIRMED Severity: normal Priority: P2 Component: binutils Assignee: unassigned at sourceware dot org Reporter: fredrick.eisele at gmail dot com Target Milestone: --- Created attachment 13981 --> https://sourceware.org/bugzilla/attachment.cgi?id=13981&action=edit A sample illustrating the underlying issue. This is a problem on Windows 10, it is related to PR 25713: "Handle extra long path names. For relative paths, convert them to absolute, in case that version is too long". When the pathname is too long (MAX_PATH) the path modified by adding a prefix '\\?\' to indicate that long path processing to be performed. This appears to work as documented here: https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation and https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation with one exception. "Because it turns off automatic expansion of the path string, the "\\?\" prefix also allows the use of ".." and "." in the path names, which can be useful if you are attempting to perform operations on a file with these otherwise reserved relative path specifiers as part of the fully qualified path." The attached program source demonstrates that there is an issue with ".." in the "long path" string. Here is the offending code from bdf/bdfio.c. [Lightly edited] ``` #elif defined (_WIN32) size_t filelen; /* PR 25713: Handle extra long path names. For relative paths, convert them to absolute, in case that version is too long. */ if (! IS_ABSOLUTE_PATH (filename) && (strstr (filename, ".o") != NULL)) { char cwd[1024]; getcwd (cwd, sizeof (cwd)); filelen = strlen (cwd) + 1; strncat (cwd, "\\", sizeof (cwd) - filelen); ++ filelen; strncat (cwd, filename, sizeof (cwd) - filelen); filename = cwd; } filelen = strlen (filename) + 1; if (filelen > MAX_PATH - 1) { FILE * file; char * fullpath; int i; fullpath = (char *) malloc (filelen + 8); /* Add a Microsoft recommended prefix that will allow the extra-long path to work. */ strcpy (fullpath, "\\\\?\\"); strcat (fullpath, filename); /* Convert any UNIX style path separators into the DOS form. */ for (i = 0; fullpath[i]; i++) { if (IS_UNIX_DIR_SEPARATOR (fullpath[i])) fullpath[i] = '\\'; } fprintf(stderr, "k25: %s %s\n", modes, fullpath); file = fopen (fullpath, modes); fprintf(stderr, "k26: %d %s\n", errno, strerror(errno)); file = close_on_exec (file); fprintf(stderr, "k27: %d %s\n", errno, strerror(errno)); free (fullpath); return file; } ``` The sample produces the following output. ``` C:\Users\fred\CLionProjects\bdfio-issue\cmake-build-debug\bdfio_issue.exe k26: 18 w+b \\?\C:\tools\foo.o k27: 0 No error k26: 28 w+b \\?\C:\tools\msys64\..\foo.o k27: 22 Invalid argument Process finished with exit code 0 ``` The sample presumes the existence of 'C:\tools\msys64\' and 'C:\tools\foo.o'. As you can see the assumption that '..' can be included in the "long path" is not correct. The error is misleading inasmuch as it implies that the problem is with the 'mode' and not the path. -- You are receiving this mail because: You are on the CC list for the bug.