Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/System.IO.FileSystem/src/System/IO/DirectoryInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,22 @@ public DirectoryInfo CreateSubdirectory(string path)
if (Path.IsPathRooted(path))
throw new ArgumentException(SR.Arg_Path2IsRooted, nameof(path));

string fullPath = Path.GetFullPath(Path.Combine(FullPath, path));
string newPath = Path.GetFullPath(Path.Combine(FullPath, path));

if (fullPath.Length < FullPath.Length
|| (fullPath.Length > FullPath.Length && !PathInternal.IsDirectorySeparator(fullPath[FullPath.Length]))
|| string.Compare(FullPath, 0, fullPath, 0, FullPath.Length, PathInternal.StringComparison) != 0)
ReadOnlySpan<char> trimmedNewPath = PathInternal.TrimEndingDirectorySeparator(newPath.AsSpan());
ReadOnlySpan<char> trimmedCurrentPath = PathInternal.TrimEndingDirectorySeparator(FullPath.AsSpan());

// We want to make sure the requested directory is actually under the subdirectory.
if (trimmedNewPath.StartsWith(trimmedCurrentPath, PathInternal.StringComparison)
// Allow the exact same path, but prevent allowing "..\FooBar" through when the directory is "Foo"
&& ((trimmedNewPath.Length == trimmedCurrentPath.Length) || PathInternal.IsDirectorySeparator(newPath[trimmedCurrentPath.Length])))
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, path, FullPath), nameof(path));
FileSystem.CreateDirectory(newPath);
return new DirectoryInfo(newPath);
}

FileSystem.CreateDirectory(fullPath);
return new DirectoryInfo(fullPath);
// We weren't nested
throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, path, FullPath), nameof(path));
}

public void Create() => FileSystem.CreateDirectory(FullPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,41 @@ public void SubDirectoryIsParentDirectory_ThrowsArgumentException()
Assert.Throws<ArgumentException>(() => new DirectoryInfo(TestDirectory + "/path").CreateSubdirectory("../../path2"));
}

[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
public void SubdirectoryOverlappingName_ThrowsArgumentException()
{
// What we're looking for here is trying to create C:\FooBar under C:\Foo by passing "..\FooBar"
DirectoryInfo info = Directory.CreateDirectory(GetTestFilePath());

string overlappingName = ".." + Path.DirectorySeparatorChar + info.Name + "overlap";

Assert.Throws<ArgumentException>(() => info.CreateSubdirectory(overlappingName));

// Now try with an info with a trailing separator
info = new DirectoryInfo(info.FullName + Path.DirectorySeparatorChar);
Assert.Throws<ArgumentException>(() => info.CreateSubdirectory(overlappingName));
}

[Theory,
MemberData(nameof(ValidPathComponentNames))]
public void ValidPathWithTrailingSlash(string component)
{
DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

string path = IOServices.AddTrailingSlashIfNeeded(component);
string path = component + Path.DirectorySeparatorChar;
DirectoryInfo result = new DirectoryInfo(testDir.FullName).CreateSubdirectory(path);

Assert.Equal(Path.Combine(testDir.FullName, path), result.FullName);
Assert.True(Directory.Exists(result.FullName));

// Now try creating subdirectories when the directory info itself has a slash
testDir = Directory.CreateDirectory(GetTestFilePath() + Path.DirectorySeparatorChar);

result = new DirectoryInfo(testDir.FullName).CreateSubdirectory(path);

Assert.Equal(Path.Combine(testDir.FullName, path), result.FullName);
Assert.True(Directory.Exists(result.FullName));
}

[Theory,
Expand All @@ -114,6 +138,13 @@ public void ValidPathWithoutTrailingSlash(string component)
Assert.Equal(Path.Combine(testDir.FullName, path), result.FullName);
Assert.True(Directory.Exists(result.FullName));

// Now try creating subdirectories when the directory info itself has a slash
testDir = Directory.CreateDirectory(GetTestFilePath() + Path.DirectorySeparatorChar);

result = new DirectoryInfo(testDir.FullName).CreateSubdirectory(path);

Assert.Equal(Path.Combine(testDir.FullName, path), result.FullName);
Assert.True(Directory.Exists(result.FullName));
}

[Fact]
Expand Down