tool_dirhie: fix to create drive-relative directory

Fix to create the top directory `foo` when specified as
`X:foo\bar\filename`, on Windows and MS-DOS. Add test to verify.

Caught by Codex Security

Follow-up to 787ee935ac #16566

Closes #21449
This commit is contained in:
Viktor Szakats 2026-04-26 13:38:47 +02:00
parent e2f84e6ba9
commit 13b6a6036c
No known key found for this signature in database
6 changed files with 133 additions and 7 deletions

View file

@ -26,7 +26,9 @@
#include "tool_dirhie.h"
#include "tool_msgs.h"
#ifdef _WIN32
#ifdef UNITTESTS
# define toolx_mkdir(x, y) create_dir_hierarchy_trace_mkdir(x)
#elif defined(_WIN32)
# include <direct.h>
# define toolx_mkdir(x, y) _mkdir(x)
#elif defined(MSDOS) && !defined(__DJGPP__)
@ -35,6 +37,22 @@
# define toolx_mkdir mkdir
#endif
#ifdef UNITTESTS
static struct dynbuf mkdir_results;
UNITTEST struct dynbuf *create_dir_hierarchy_trace_dynres(void)
{
return &mkdir_results;
}
static int create_dir_hierarchy_trace_mkdir(const char *dir)
{
return !dir ||
curlx_dyn_add(&mkdir_results, dir) ||
curlx_dyn_add(&mkdir_results, "|") ? -1 : 0;
}
#endif
static void show_dir_errno(const char *name)
{
switch(errno) {
@ -105,12 +123,11 @@ CURLcode create_dir_hierarchy(const char *outfile)
#if defined(_WIN32) || defined(MSDOS)
if(!curlx_dyn_len(&dirbuf)) {
/* Skip creating a drive's current directory. It may seem as though that
would harmlessly fail but it could be a corner case if X: did not
exist, since we would be creating it erroneously. eg if outfile is
X:\foo\bar\filename then do not mkdir X: This logic takes into
/* Skip creating a standalone Windows/MS-DOS drive letter 'X:', e.g.
if outfile is X:\foo\bar\filename. Do create drive-relative
directories e.g. in outfile X:foo\bar\filename. This logic takes into
account unsupported drives !:, 1:, etc. */
if(len > 1 && (outfile[1] == ':'))
if(len == 2 && (outfile[1] == ':'))
skip = TRUE;
}
#endif

View file

@ -25,6 +25,10 @@
***************************************************************************/
#include "tool_setup.h"
#ifdef UNITTESTS
UNITTEST struct dynbuf *create_dir_hierarchy_trace_dynres(void);
#endif
CURLcode create_dir_hierarchy(const char *outfile);
#endif /* HEADER_CURL_TOOL_DIRHIE_H */