zig icon indicating copy to clipboard operation
zig copied to clipboard

std.ChildProcess.exec crashes if PATH is empty

Open andrewrk opened this issue 3 years ago • 2 comments
trafficstars

Zig Version: 0.10.0-dev.3979+aec0e595f

To reproduce, export PATH="" then use std.ChildProcess.exec API:

thread 464064 panic: invalid error code
/home/andy/dev/zig/lib/std/child_process.zig:515:21: 0x34952a6 in cleanupAfterWait (zig)
                    return @errSetCast(SpawnError, @intToError(err_int));
                    ^
/home/andy/dev/zig/lib/std/child_process.zig:478:42: 0x3224b53 in handleWaitResult (zig)
        self.term = self.cleanupAfterWait(status);
                                         ^
/home/andy/dev/zig/lib/std/child_process.zig:474:30: 0x3224870 in waitUnwrapped (zig)
        self.handleWaitResult(status);
                             ^
/home/andy/dev/zig/lib/std/child_process.zig:445:31: 0x3224754 in waitPosix (zig)
        try self.waitUnwrapped();
                              ^
/home/andy/dev/zig/lib/std/child_process.zig:187:34: 0x3224601 in wait (zig)
            return self.waitPosix();
                                 ^
/home/andy/dev/zig/lib/std/child_process.zig:423:35: 0x3503d96 in exec (zig)
            .term = try child.wait(),
                                  ^
/home/andy/dev/zig/src/libc_installation.zig:264:47: 0x32bb1fc in findNativeIncludeDirPosix (zig)
        const exec_res = std.ChildProcess.exec(.{
                                              ^
/home/andy/dev/zig/src/libc_installation.zig:209:47: 0x3067665 in findNative (zig)
            try self.findNativeIncludeDirPosix(args);
                                              ^
/home/andy/dev/zig/src/Compilation.zig:4552:45: 0x3065c79 in detectLibCIncludeDirs (zig)
        libc.* = LibCInstallation.findNative(.{ .allocator = arena }) catch |err| switch (err) {
                                            ^
/home/andy/dev/zig/src/Compilation.zig:1235:52: 0x3098d8e in create (zig)
        const libc_dirs = try detectLibCIncludeDirs(
                                                   ^
/home/andy/dev/zig/src/main.zig:2955:34: 0x300f90d in buildOutputType (zig)
        .libc_installation = if (libc_installation) |*lci| lci else null,
                                 ^
/home/andy/dev/zig/src/main.zig:230:31: 0x2feb468 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .{ .build = .Exe });
                              ^
/home/andy/dev/zig/src/main.zig:174:20: 0x2feab80 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/home/andy/dev/zig/lib/std/start.zig:578:37: 0x2fed0a9 in main (zig)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x7f678ef7e236 in ??? (???)
???:?:?: 0x7ffcfcb23eab in ??? (???)
Aborted (core dumped)

andrewrk avatar Sep 11 '22 22:09 andrewrk

My src/main.zig:

const std = @import("std");

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();
    _ = try std.ChildProcess.exec(.{
        .allocator = allocator,
        .argv = &.{ "git", "status" },
    });
}
$ PATH="/sbin/" zig-out/bin/build
error: FileNotFound
/home/bratishkaerik/zig/lib/std/child_process.zig:446:9: 0x20fdb5 in waitPosix (build)
        return self.term.?;
        ^
/home/bratishkaerik/zig/lib/std/child_process.zig:187:13: 0x20fc8f in wait (build)
            return self.waitPosix();
            ^
/home/bratishkaerik/zig/lib/std/child_process.zig:423:21: 0x21040b in exec (build)
            .term = try child.wait(),
                    ^
/home/bratishkaerik/zig/build/src/main.zig:7:9: 0x21086d in main (build)
    _ = try std.ChildProcess.exec(.{
$ PATH="" zig-out/bin/build
thread 25501 panic: invalid error code
/home/bratishkaerik/zig/lib/std/child_process.zig:515:21: 0x215e72 in cleanupAfterWait (build)
                    return @errSetCast(SpawnError, @intToError(err_int));
                    ^
/home/bratishkaerik/zig/lib/std/child_process.zig:478:42: 0x2100bb in handleWaitResult (build)
        self.term = self.cleanupAfterWait(status);
                                         ^
/home/bratishkaerik/zig/lib/std/child_process.zig:474:30: 0x20fe23 in waitUnwrapped (build)
        self.handleWaitResult(status);
                             ^
/home/bratishkaerik/zig/lib/std/child_process.zig:445:31: 0x20fd4b in waitPosix (build)
        try self.waitUnwrapped();
                              ^
/home/bratishkaerik/zig/lib/std/child_process.zig:187:34: 0x20fc64 in wait (build)
            return self.waitPosix();
                                 ^
/home/bratishkaerik/zig/lib/std/child_process.zig:423:35: 0x2103ca in exec (build)
            .term = try child.wait(),
                                  ^
/home/bratishkaerik/zig/build/src/main.zig:7:34: 0x210843 in main (build)
    _ = try std.ChildProcess.exec(.{
                                 ^
/home/bratishkaerik/zig/lib/std/start.zig:578:37: 0x20eb82 in posixCallMainAndExit (build)
            const result = root.main() catch |err| {
                                    ^
/home/bratishkaerik/zig/lib/std/start.zig:340:5: 0x20e542 in _start (build)
    @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    ^
[1]    25501 IOT instruction  PATH="" zig-out/bin/build
$ unset PATH
$ zig-out/bin/build

Nothing, succesful exit (some garbage about zsh theming unable to find cat)

BratishkaErik avatar Sep 12 '22 15:09 BratishkaErik

@BratishkaErik I can not reproduce with Linux your result for PATH="/sbin/" zig-out/bin/build. What OS are you using?

PATH="" ./tmp also fails. I am currently debugging (fixing up my gdb skills).

gdbscr:

set env PATH ""
set follow-fork-mode child
b os.zig:1811

gdb -x gdbscr ./tmp

1838            err = execveZ(full_path, child_argv, envp);
(ins)(gdb) p full_path 
$2 = (u8 *) 0x7fffffffc640 "\"\"/git"

\"\"git is definitely a wrong expansion. The logic looks like it is too naive and does not handle edge cases yet.

For future readers: Try to reproduce on fda6d44778f3faf53c66945a0db65be68113416f with rr record -x gdbscr ./tmp after building above mentioned example with zig build-exe tmp.zig. :)

matu3ba avatar Sep 13 '22 22:09 matu3ba

It seems like the "invalid error code" panic, is due to var err: ExecveError = undefined;. I think we should make it var err: ExecveError = error.FileNotFound; which ends up making the error msg the same if we were to try and execute a command that isn't present on the path.

cod1r avatar Sep 15 '22 20:09 cod1r