Make std.process.browse @safe and sync attributes for windows/posix

Add `@trusted` wrappers for calls to C functions that are always
called with valid arguments.
This commit is contained in:
MoonlightSentinel 2021-04-27 10:45:11 +02:00
parent 19264401a8
commit fa905436d9
No known key found for this signature in database
GPG key ID: 1A1A60AECDC956AB

View file

@ -4134,7 +4134,7 @@ version (Windows)
pragma(lib,"shell32.lib"); pragma(lib,"shell32.lib");
void browse(scope const(char)[] url) void browse(scope const(char)[] url) nothrow @nogc @trusted
{ {
ShellExecuteW(null, "open", url.tempCStringW(), null, null, SW_SHOWNORMAL); ShellExecuteW(null, "open", url.tempCStringW(), null, null, SW_SHOWNORMAL);
} }
@ -4145,25 +4145,28 @@ else version (Posix)
import core.stdc.string; import core.stdc.string;
import core.sys.posix.unistd; import core.sys.posix.unistd;
void browse(scope const(char)[] url) nothrow @nogc void browse(scope const(char)[] url) nothrow @nogc @safe
{ {
const(char)*[3] args; const(char)*[3] args;
const(char)* browser = core.stdc.stdlib.getenv("BROWSER"); // Trusted because it's called with a zero-terminated literal
const(char)* browser = (() @trusted => core.stdc.stdlib.getenv("BROWSER"))();
if (browser) if (browser)
{ browser = strdup(browser); {
// String already zero-terminated
browser = (() @trusted => strdup(browser))();
args[0] = browser; args[0] = browser;
} }
else else
{ {
version (OSX) version (OSX)
{ {
args[0] = "open".ptr; args[0] = "open";
} }
else else
{ {
//args[0] = "x-www-browser".ptr; // doesn't work on some systems //args[0] = "x-www-browser"; // doesn't work on some systems
args[0] = "xdg-open".ptr; args[0] = "xdg-open";
} }
} }
@ -4174,18 +4177,22 @@ else version (Posix)
auto childpid = core.sys.posix.unistd.fork(); auto childpid = core.sys.posix.unistd.fork();
if (childpid == 0) if (childpid == 0)
{ {
core.sys.posix.unistd.execvp(args[0], cast(char**) args.ptr); // Trusted because args and all entries are always zero-terminated
perror(args[0]); // failed to execute (() @trusted =>
core.sys.posix.unistd.execvp(args[0], &args[0]) ||
perror(args[0]) // failed to execute
)();
return; return;
} }
if (browser) if (browser)
free(cast(void*) browser); // Trusted because it's allocated via strdup above
(() @trusted => free(cast(void*) browser))();
version (StdUnittest) version (StdUnittest)
{ {
// Verify that the test script actually suceeds // Verify that the test script actually suceeds
int status; int status;
const check = waitpid(childpid, &status, 0); const check = (() @trusted => waitpid(childpid, &status, 0))();
assert(check != -1); assert(check != -1);
assert(status == 0); assert(status == 0);
} }
@ -4194,6 +4201,13 @@ else version (Posix)
else else
static assert(0, "os not supported"); static assert(0, "os not supported");
// Verify attributes are consistent between all implementations
@safe @nogc nothrow unittest
{
if (false)
browse("");
}
version (Windows) { /* Doesn't use BROWSER */ } version (Windows) { /* Doesn't use BROWSER */ }
else else
@system unittest @system unittest