Thread overview
Possible runtime bug in preprocessing of command line arguments passed to the D main
Oct 24, 2021
Basile B.
Oct 24, 2021
Basile B.
Oct 24, 2021
jfondren
Oct 24, 2021
Basile B.
Oct 24, 2021
Brian Callahan
October 24, 2021

The following code, on linux

module runnable;
​
extern(C) int execv(const char* p, const char** args);
​
immutable src = `
    import std.getopt;
    void main(string[] args)
    {
        bool c;
        getopt(args, "c", &c);
    }
`;
​
void prepareProgram()
{
    import std.process  : execute;
    import std.file     : write;
    write("a.d", src);
    execute(["dmd", "a.d"]);
}
​
void main(string[] args)
{
    prepareProgram();
    execv("a", null);
}

results in a std.getopt exception:

>

object.Exception@/usr/include/dmd/phobos/std/getopt.d(423): Invalid arguments string passed: program name missing

Context is a program not written in D that uses execv to call a D program that uses getopt.

What do you think ?

October 24, 2021

On Sunday, 24 October 2021 at 14:21:52 UTC, Basile B. wrote:

>

The following code, on linux
[...]
What do you think ?

Forgot to say that this change

- execv("a", null);
+ execv("a", ["whatever".ptr].ptr);

makes the problem goes away, so it would be caused by how null args are handled, presumably.

October 24, 2021

On Sunday, 24 October 2021 at 14:21:52 UTC, Basile B. wrote:

>

What do you think ?

I'm very surprised that this is even allowed. Apparently it's Linux userspace that normally complains about it: https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/progname.c#n54

The manpages just say

   v - execv(), execvp(), execvpe()
       The char *const argv[] argument is an array of pointers to null-terminated strings  that  represent
       the argument list available to the new program.  The first argument, by convention, should point to
       the filename associated with the file being executed.  The array of pointers must be terminated  by
       a null pointer.

With nothing to the contrary, I'd take "must be terminated by a null pointer" as "can't itself be a null pointer".

On OpenBSD this fails outright:

RET   execve -1 errno 14 Bad address

You can get execv from core.sys.posix.unistd

October 24, 2021

On Sunday, 24 October 2021 at 14:38:44 UTC, jfondren wrote:

>

[...]

With nothing to the contrary, I'd take "must be terminated by a null pointer" as "can't itself be a null pointer".

ah yeah, and thanks, of course ... how would the count of arg be known without the sentinel...

October 24, 2021

On Sunday, 24 October 2021 at 14:38:44 UTC, jfondren wrote:

>

With nothing to the contrary, I'd take "must be terminated by a null pointer" as "can't itself be a null pointer".

The execve(2) is more explicit:
"The argument argv is a pointer to a null-terminated array of character pointers to NUL-terminated character strings. These strings construct the argument list to be made available to the new process. At least one non-null argument must be present in the array; by custom, the first element should be the name of the executed program (for example, the last component of path)."