Commit ee5b4d786 for clamav.net
commit ee5b4d786705fd462900c0d4fb47d1607c3a8293
Author: Val S. <mx.val@icloud.com>
Date: Thu Nov 13 16:35:08 2025 -0500
Windows: Fix issue creating new temp subdirectory
On Windows, when scanning some files with `--leave-temps` enabled and
with `--tempdir` set to something like `C:\temp`, it may fail to create
a new subdirectory to store the temp files because the absolute file
path is too long for the `mkdir()` function.
The `mkdir()` function may fail on Windows if the filepath is longer than
the legacy MAX_PATH.
Fixing this in C or C++ is rather difficult, requiring either a registry
key + application manifest change, or else converting the path to UTF16
and UNC format (i.e. `"\\?\C:\temp"`) to pass to `CreateDirectoryW()`.
The solution in this commit is to use the Rust `std` library instead. It
is able to handle the longer file paths without issue.
CLAM-2924
diff --git a/libclamav/others.c b/libclamav/others.c
index ee3cf32eb..d191ae25f 100644
--- a/libclamav/others.c
+++ b/libclamav/others.c
@@ -1771,6 +1771,10 @@ cl_error_t cli_recursion_stack_push(cli_ctx *ctx, cl_fmap_t *map, cli_file_t typ
char *new_temp_path = NULL;
char *fmap_basename = NULL;
+#ifdef _WIN32
+ FFIError *mkdir_w32_error = NULL;
+#endif
+
old_recursion_level = ctx->recursion_level;
// Check the regular limits
@@ -1869,11 +1873,21 @@ cl_error_t cli_recursion_stack_push(cli_ctx *ctx, cl_fmap_t *map, cli_file_t typ
}
}
+#ifdef _WIN32
+
+ if (!mkdir_w32(new_temp_path, &mkdir_w32_error)) {
+ cli_errmsg("cli_magic_scan: Can't create tmp sub-directory (%s) for scan. Error: %s\n", new_temp_path, ffierror_fmt(mkdir_w32_error));
+ ffierror_free(mkdir_w32_error);
+ status = CL_EACCES;
+ goto done;
+ }
+#else
if (mkdir(new_temp_path, 0700)) {
- cli_errmsg("cli_magic_scan: Can't create tmp sub-directory for scan: %s.\n", new_temp_path);
+ cli_errmsg("cli_magic_scan: Can't create tmp sub-directory (%s) for scan. Error: %s\n", new_temp_path, strerror(errno));
status = CL_EACCES;
goto done;
}
+#endif
ctx->recursion_stack[ctx->recursion_level].tmpdir = new_temp_path;
ctx->this_layer_tmpdir = new_temp_path;
diff --git a/libclamav_rust/cbindgen.toml b/libclamav_rust/cbindgen.toml
index d404dc84a..52d4f4e35 100644
--- a/libclamav_rust/cbindgen.toml
+++ b/libclamav_rust/cbindgen.toml
@@ -59,6 +59,7 @@ include = [
"scanners::scan_onenote",
"scanners::cli_scanalz",
"util::glob_rm",
+ "util::mkdir_w32",
]
# prefix = "CAPI_"
diff --git a/libclamav_rust/src/util.rs b/libclamav_rust/src/util.rs
index fdd41b40c..c07793666 100644
--- a/libclamav_rust/src/util.rs
+++ b/libclamav_rust/src/util.rs
@@ -165,3 +165,20 @@ pub unsafe extern "C" fn glob_rm(glob_str: *const c_char, err: *mut *mut FFIErro
true
}
+
+/// C interface to create a directory
+///
+/// # Safety
+///
+/// No parameters may be NULL.
+#[export_name = "mkdir_w32"]
+pub unsafe extern "C" fn mkdir_w32(path: *const c_char, err: *mut *mut FFIError) -> bool {
+ let path = validate_str_param!(path);
+
+ if let Err(e) = std::fs::create_dir_all(&path) {
+ warn!("Failed to create directory: {path:?}");
+ return ffi_error!(err = err, Error::IoError(e));
+ }
+
+ true
+}