Merge pull request #5410 from jmdavis/path

Fix safety issues with driveName, stripDrive, and rootName
This commit is contained in:
Sebastian Wilzbach 2018-01-28 02:12:46 +01:00 committed by GitHub
commit 70d3b892ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -688,9 +688,21 @@ if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementT
A slice of $(D path).
*/
auto rootName(R)(R path)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) ||
isNarrowString!R) &&
!isConvertibleToString!R)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R)
{
return _rootName(path);
}
/// ditto
auto rootName(C)(C[] path)
if (isSomeChar!C)
{
return _rootName(path);
}
private auto _rootName(R)(R path)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) ||
isNarrowString!R)
{
if (path.empty)
goto Lnull;
@ -742,6 +754,12 @@ Lnull:
@safe unittest
{
assert(testAliasedString!rootName("/foo/bar"));
enum S : string { a = "/foo/bar" }
assert(S.a.rootName == "/");
char[S.a.length] sa = S.a[];
assert(sa.rootName == "/");
}
@safe unittest
@ -763,12 +781,6 @@ Lnull:
}
}
auto rootName(R)(R path)
if (isConvertibleToString!R)
{
return rootName!(StringTypeOf!R)(path);
}
/**
Get the drive portion of a path.
@ -784,9 +796,21 @@ if (isConvertibleToString!R)
Always returns an empty range on POSIX.
*/
auto driveName(R)(R path)
if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) ||
isNarrowString!R) &&
!isConvertibleToString!R)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R)
{
return _driveName(path);
}
/// ditto
auto driveName(C)(C[] path)
if (isSomeChar!C)
{
return _driveName(path);
}
private auto _driveName(R)(R path)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) ||
isNarrowString!R)
{
version (Windows)
{
@ -820,15 +844,20 @@ if ((isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(Element
}
}
auto driveName(R)(auto ref R path)
if (isConvertibleToString!R)
{
return driveName!(StringTypeOf!R)(path);
}
@safe unittest
{
assert(testAliasedString!driveName(`d:\file`));
assert(testAliasedString!driveName("d:/file"));
version(Posix)
immutable result = "";
else version(Windows)
immutable result = "d:";
enum S : string { a = "d:/file" }
assert(S.a.driveName == result);
char[S.a.length] sa = S.a[];
assert(sa.driveName == result);
}
@safe unittest
@ -861,9 +890,20 @@ if (isConvertibleToString!R)
Returns: A slice of path without the drive component.
*/
auto stripDrive(R)(R path)
if ((isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) ||
isNarrowString!R) &&
!isConvertibleToString!R)
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) && !isSomeString!R)
{
return _stripDrive(path);
}
/// ditto
auto stripDrive(C)(C[] path)
{
return _stripDrive(path);
}
private auto _stripDrive(R)(R path)
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) ||
isNarrowString!R)
{
version(Windows)
{
@ -883,15 +923,20 @@ if ((isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) ||
}
}
auto stripDrive(R)(auto ref R path)
if (isConvertibleToString!R)
{
return stripDrive!(StringTypeOf!R)(path);
}
@safe unittest
{
assert(testAliasedString!stripDrive(`d:\dir\file`));
assert(testAliasedString!stripDrive("d:/dir/file"));
version(Posix)
immutable result = "d:/dir/file";
else version(Windows)
immutable result = "/dir/file";
enum S : string { a = "d:/dir/file" }
assert(S.a.stripDrive == result);
char[S.a.length] sa = S.a[];
assert(sa.stripDrive == result);
}
@safe unittest