Skip to content

Commit f6e4416

Browse files
committed
Fix Issue 18178 - std.path should be usable in @safe
1 parent ac1dc46 commit f6e4416

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

std/path.d

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3916,7 +3916,7 @@ if (isConvertibleToString!Range)
39163916
}
39173917
-----
39183918
*/
3919-
string expandTilde(string inputPath) nothrow
3919+
string expandTilde(string inputPath) @safe nothrow
39203920
{
39213921
version(Posix)
39223922
{
@@ -3930,9 +3930,10 @@ string expandTilde(string inputPath) nothrow
39303930
is joined to path[char_pos .. length] if char_pos is smaller
39313931
than length, otherwise path is not appended to c_path.
39323932
*/
3933-
static string combineCPathWithDPath(char* c_path, string path, size_t char_pos) nothrow
3933+
static string combineCPathWithDPath(char* c_path, string path, size_t char_pos) @trusted nothrow
39343934
{
39353935
import core.stdc.string : strlen;
3936+
import std.exception : assumeUnique;
39363937

39373938
assert(c_path != null);
39383939
assert(path.length > 0);
@@ -3945,11 +3946,10 @@ string expandTilde(string inputPath) nothrow
39453946
if (end && isDirSeparator(c_path[end - 1]))
39463947
end--;
39473948

3948-
// (this is the only GC allocation done in expandTilde())
39493949
string cp;
39503950
if (char_pos < path.length)
39513951
// Append something from path
3952-
cp = cast(string)(c_path[0 .. end] ~ path[char_pos .. $]);
3952+
cp = assumeUnique(c_path[0 .. end] ~ path[char_pos .. $]);
39533953
else
39543954
// Create our own copy, as lifetime of c_path is undocumented
39553955
cp = c_path[0 .. end].idup;
@@ -3958,23 +3958,23 @@ string expandTilde(string inputPath) nothrow
39583958
}
39593959

39603960
// Replaces the tilde from path with the environment variable HOME.
3961-
static string expandFromEnvironment(string path) nothrow
3961+
static string expandFromEnvironment(string path) @safe nothrow
39623962
{
39633963
import core.stdc.stdlib : getenv;
39643964

39653965
assert(path.length >= 1);
39663966
assert(path[0] == '~');
39673967

39683968
// Get HOME and use that to replace the tilde.
3969-
auto home = getenv("HOME");
3969+
auto home = () @trusted { return getenv("HOME"); } ();
39703970
if (home == null)
39713971
return path;
39723972

39733973
return combineCPathWithDPath(home, path, 1);
39743974
}
39753975

39763976
// Replaces the tilde from path with the path from the user database.
3977-
static string expandFromDatabase(string path) nothrow
3977+
static string expandFromDatabase(string path) @safe nothrow
39783978
{
39793979
// bionic doesn't really support this, as getpwnam_r
39803980
// isn't provided and getpwnam is basically just a stub
@@ -3994,10 +3994,7 @@ string expandTilde(string inputPath) nothrow
39943994
auto last_char = indexOf(path, dirSeparator[0]);
39953995

39963996
size_t username_len = (last_char == -1) ? path.length : last_char;
3997-
char* username = cast(char*) malloc(username_len * char.sizeof);
3998-
if (!username)
3999-
onOutOfMemoryError();
4000-
scope(exit) free(username);
3997+
char[] username = new char[username_len * char.sizeof];
40013998

40023999
if (last_char == -1)
40034000
{
@@ -4017,24 +4014,27 @@ string expandTilde(string inputPath) nothrow
40174014
uint extra_memory_size = 2;
40184015
else
40194016
uint extra_memory_size = 5 * 1024;
4020-
char* extra_memory;
4021-
scope(exit) free(extra_memory);
4017+
char[] extra_memory;
40224018

40234019
passwd result;
40244020
while (1)
40254021
{
4026-
extra_memory = cast(char*) realloc(extra_memory, extra_memory_size * char.sizeof);
4027-
if (extra_memory == null)
4028-
onOutOfMemoryError();
4022+
extra_memory.length += extra_memory_size;
40294023

40304024
// Obtain info from database.
40314025
passwd *verify;
40324026
errno = 0;
4033-
if (getpwnam_r(username, &result, extra_memory, extra_memory_size,
4034-
&verify) == 0)
4027+
auto passResult = () @trusted { return getpwnam_r(
4028+
&username[0],
4029+
&result,
4030+
&extra_memory[0],
4031+
extra_memory.length,
4032+
&verify
4033+
); } ();
4034+
if (passResult == 0)
40354035
{
40364036
// Succeeded if verify points at result
4037-
if (verify == &result)
4037+
if (verify == () @trusted { return &result; } ())
40384038
// username is found
40394039
path = combineCPathWithDPath(result.pw_dir, path, last_char);
40404040
break;

0 commit comments

Comments
 (0)