Skip to content

Commit 7ac4afa

Browse files
committed
fix(vxcore): canonicalize the notebook root when rejecting in-notebook imports
ImportFolder canonicalized only the external path and compared it against the raw stored root, so the containment guard silently passed whenever the two spellings of the same location differ. On the Windows CI runner TEMP is the 8.3 short path C:/Users/RUNNER~1/..., while fs::canonical resolves the external path to C:/Users/runneradmin/... - the prefix never matched and a folder inside the notebook was happily imported into itself. Symlinked roots hit the same hole on every platform. Both sides now go through fs::weakly_canonical. Reproduced locally by pointing TMP/TEMP at an 8.3 alias: test_folder_import_within_notebook fails before the change and passes after.
1 parent d07a5b0 commit 7ac4afa

2 files changed

Lines changed: 18 additions & 8 deletions

File tree

src/core/bundled_folder_manager.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,12 +2284,18 @@ VxCoreError BundledFolderManager::ImportFolder(const std::string &dest_folder_pa
22842284

22852285
// Reject importing a folder from within the notebook root to prevent circular copies
22862286
try {
2287-
fs::path canonical_external = fs::canonical(external_path);
2288-
fs::path root_path = PathFromUtf8(notebook_->GetRootFolder());
2287+
// BOTH sides must be canonicalized before comparing. Canonicalizing only
2288+
// the external path made the check silently pass whenever the two spellings
2289+
// of the same location differ — e.g. on Windows where the notebook root was
2290+
// opened through an 8.3 short path (C:/Users/RUNNER~1/...) while
2291+
// fs::canonical resolves the external path to the long form
2292+
// (C:/Users/runneradmin/...), or anywhere a symlink is in play.
2293+
fs::path canonical_external = fs::weakly_canonical(external_path);
2294+
fs::path canonical_root = fs::weakly_canonical(PathFromUtf8(notebook_->GetRootFolder()));
22892295
// Check if external path starts with (is under) notebook root
2290-
auto mismatch_pair = std::mismatch(root_path.begin(), root_path.end(),
2296+
auto mismatch_pair = std::mismatch(canonical_root.begin(), canonical_root.end(),
22912297
canonical_external.begin(), canonical_external.end());
2292-
if (mismatch_pair.first == root_path.end()) {
2298+
if (mismatch_pair.first == canonical_root.end()) {
22932299
// root_path is a prefix of canonical_external (external is inside notebook)
22942300
VXCORE_LOG_ERROR("ImportFolder: Cannot import folder from within notebook root: %s",
22952301
external_folder_path.c_str());

src/core/raw_folder_manager.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,11 +1729,15 @@ VxCoreError RawFolderManager::ImportFolder(const std::string &dest_folder_path,
17291729

17301730
// Reject importing from within the notebook root
17311731
try {
1732-
fs::path canonical_external = fs::canonical(external_path);
1733-
fs::path root_path = PathFromUtf8(notebook_->GetRootFolder());
1734-
auto mismatch_pair = std::mismatch(root_path.begin(), root_path.end(),
1732+
// BOTH sides must be canonicalized — see the same guard in
1733+
// BundledFolderManager::ImportFolder for why comparing a raw root against a
1734+
// canonicalized external path misses containment (8.3 short paths,
1735+
// symlinks).
1736+
fs::path canonical_external = fs::weakly_canonical(external_path);
1737+
fs::path canonical_root = fs::weakly_canonical(PathFromUtf8(notebook_->GetRootFolder()));
1738+
auto mismatch_pair = std::mismatch(canonical_root.begin(), canonical_root.end(),
17351739
canonical_external.begin(), canonical_external.end());
1736-
if (mismatch_pair.first == root_path.end()) {
1740+
if (mismatch_pair.first == canonical_root.end()) {
17371741
VXCORE_LOG_ERROR("ImportFolder: Cannot import folder from within notebook root: %s",
17381742
external_folder_path.c_str());
17391743
return VXCORE_ERR_INVALID_PARAM;

0 commit comments

Comments
 (0)