Skip to content

Commit

Permalink
fs: fix crash when path contains %
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 committed Oct 4, 2024
1 parent d2ad9b4 commit b82d3c5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 33 deletions.
53 changes: 21 additions & 32 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3179,44 +3179,37 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
if (!error_code) {
// Check if src and dest are identical.
if (std::filesystem::equivalent(src_path, dest_path)) {
std::u8string message =
u8"src and dest cannot be the same " + dest_path.u8string();
std::string message = "src and dest cannot be the same %s";
return THROW_ERR_FS_CP_EINVAL(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), dest_path.string());
}

const bool dest_is_dir =
dest_status.type() == std::filesystem::file_type::directory;

if (src_is_dir && !dest_is_dir) {
std::u8string message = u8"Cannot overwrite non-directory " +
src_path.u8string() + u8" with directory " +
dest_path.u8string();
std::string message = "Cannot overwrite non-directory %s with directory %s";
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), src_path.string(), dest_path.string());
}

if (!src_is_dir && dest_is_dir) {
std::u8string message = u8"Cannot overwrite directory " +
dest_path.u8string() + u8" with non-directory " +
src_path.u8string();
std::string message = "Cannot overwrite directory %s with non-directory %s";
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), dest_path.string(), src_path.string());
}
}

std::u8string dest_path_str = dest_path.u8string();
std::u8string src_path_str = src_path.u8string();
std::string dest_path_str = dest_path.string();
std::string src_path_str = src_path.string();
if (!src_path_str.ends_with(std::filesystem::path::preferred_separator)) {
src_path_str += std::filesystem::path::preferred_separator;
}
// Check if dest_path is a subdirectory of src_path.
if (src_is_dir && dest_path_str.starts_with(src_path_str)) {
std::u8string message = u8"Cannot copy " + src_path.u8string() +
u8" to a subdirectory of self " +
dest_path.u8string();
std::string message = "Cannot copy %s to a subdirectory of self %s";
return THROW_ERR_FS_CP_EINVAL(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), src_path_str, dest_path_str);
}

auto dest_parent = dest_path.parent_path();
Expand All @@ -3227,11 +3220,9 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
dest_parent.parent_path() != dest_parent) {
if (std::filesystem::equivalent(
src_path, dest_path.parent_path(), error_code)) {
std::u8string message = u8"Cannot copy " + src_path.u8string() +
u8" to a subdirectory of self " +
dest_path.u8string();
std::string message = "Cannot copy %s to a subdirectory of self %s";
return THROW_ERR_FS_CP_EINVAL(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), src_path_str, dest_path_str);
}

// If equivalent fails, it's highly likely that dest_parent does not exist
Expand All @@ -3243,29 +3234,27 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
}

if (src_is_dir && !recursive) {
std::u8string message =
u8"Recursive option not enabled, cannot copy a directory: " +
src_path.u8string();
std::string message = "Recursive option not enabled, cannot copy a directory: %s";
return THROW_ERR_FS_EISDIR(env,
reinterpret_cast<const char*>(message.c_str()));
message.c_str(),
src_path_str);
}

switch (src_status.type()) {
case std::filesystem::file_type::socket: {
std::u8string message = u8"Cannot copy a socket file: " + dest_path_str;
std::string message = "Cannot copy a socket file: %s";
return THROW_ERR_FS_CP_SOCKET(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), dest_path_str);
}
case std::filesystem::file_type::fifo: {
std::u8string message = u8"Cannot copy a FIFO pipe: " + dest_path_str;
std::string message = "Cannot copy a FIFO pipe: %s";
return THROW_ERR_FS_CP_FIFO_PIPE(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), dest_path_str);
}
case std::filesystem::file_type::unknown: {
std::u8string message =
u8"Cannot copy an unknown file type: " + dest_path_str;
std::string message = "Cannot copy an unknown file type: %s";
return THROW_ERR_FS_CP_UNKNOWN(
env, reinterpret_cast<const char*>(message.c_str()));
env, message.c_str(), dest_path_str);
}
default:
break;
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-fs-cp.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ function nextdir(dirname) {
{
const src = nextdir();
mkdirSync(join(src, 'a'), mustNotMutateObjectDeep({ recursive: true }));
const dest = nextdir();
const dest = nextdir('%');
// Create symlink in dest pointing to src.
const destLink = join(dest, 'b');
mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true }));
Expand Down

0 comments on commit b82d3c5

Please sign in to comment.