Skip to content

Commit 029b94c

Browse files
committed
Check normalized and not normalized versions of parent and link
The "toRealPath()" of the child should with "realParentPath" to avoid silent NoSuchFileException's if the constructed link does not match actual (fully resolved) file system state of the local file we are checking. Fixes #2220
1 parent 018c667 commit 029b94c

File tree

1 file changed

+25
-9
lines changed
  • resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore

1 file changed

+25
-9
lines changed

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -523,19 +523,12 @@ private boolean isRecursiveLink(IFileStore parentStore, IFileInfo localInfo) {
523523
if (disable_advanced_recursive_link_checks) {
524524
// Multiple ../ backwards links can go outside the project tree
525525
if (linkTarget != null && PatternHolder.REPEATING_BACKWARDS_PATTERN.matcher(linkTarget).matches()) {
526-
Path targetPath = parent.resolve(linkTarget).normalize();
527-
528-
// Recursive if literal target points to the literal parent of this tree
529-
if (parent.normalize().startsWith(targetPath)) {
526+
if (isRecursiveBackwardsLink(parent, linkTarget, false)) {
530527
return true;
531528
}
532-
533-
// Recursive if resolved target points to the resolved parent of this tree
534-
Path realTargetPath = targetPath.toRealPath();
535-
if (realParentPath.startsWith(realTargetPath)) {
529+
if (isRecursiveBackwardsLink(realParentPath, linkTarget, true)) {
536530
return true;
537531
}
538-
539532
// If link is outside the project tree, consider as non recursive
540533
// The link still can create recursion in the tree, but we can't detect it here.
541534
}
@@ -573,6 +566,29 @@ private boolean isRecursiveLink(IFileStore parentStore, IFileInfo localInfo) {
573566
return false;
574567
}
575568

569+
private static boolean isRecursiveBackwardsLink(Path parent, String linkTarget, boolean resolveRealTarget)
570+
throws IOException {
571+
// Cheap tests first
572+
// Recursive if literal target points to the literal parent of this tree
573+
Path notNormalizedLink = parent.resolve(linkTarget);
574+
if (parent.startsWith(notNormalizedLink)) {
575+
return true;
576+
}
577+
// Same as above but using normalized variants
578+
Path normalizedLink = notNormalizedLink.normalize();
579+
if (parent.normalize().startsWith(normalizedLink)) {
580+
return true;
581+
}
582+
// Next check costs more time because it does real IO when resolving paths
583+
if (resolveRealTarget) {
584+
Path realTarget = normalizedLink.toRealPath();
585+
if (parent.startsWith(realTarget)) {
586+
return true;
587+
}
588+
}
589+
return false;
590+
}
591+
576592
protected boolean isValidLevel(int currentLevel, int depth) {
577593
return switch (depth) {
578594
case IResource.DEPTH_INFINITE -> true;

0 commit comments

Comments
 (0)