【问题标题】:Can exec*'s argv contain a value of 0 in multiple places?exec* 的 argv 可以在多个位置包含值 0 吗?
【发布时间】:2018-09-24 09:01:19
【问题描述】:

我读到exec创建一个新进程后,

argv 是一个参数字符串数组,带有argv[argc] == 0

如果数组argv 中的其他值之一恰好为0,会发生什么?子进程运行时,参数个数(argc)会不会计算错误?

我在 AMD64 (https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf) 的 ABI 第 34 页上读到了这篇文章。

【问题讨论】:

    标签: linux x86 exec posix abi


    【解决方案1】:

    execve 系统调用(由所有exec* 函数使用)具有char *const argv[] 形式的参数。内核通过将提供的argv 迭代为follows 来计算argc

    static int count(struct user_arg_ptr argv, int max)
    {
        int i = 0;
    
        if (argv.ptr.native != NULL) {
            for (;;) {
                const char __user *p = get_user_arg_ptr(argv, i);
    
                if (!p)
                    break;
    
                if (IS_ERR(p))
                    return -EFAULT;
    
                if (i >= max)
                    return -E2BIG;
                ++i;
    
                if (fatal_signal_pending(current))
                    return -ERESTARTNOHAND;
                cond_resched();
            }
        }
        return i;
    }
    

    函数get_user_arg_ptr 实质上计算argv 数组的索引并返回存储在该索引处的指针。循环在四种情况下中断,其中两种与您的问题有关:

    • 在 argv 数组中看到的第一个 NULL。如果argv 中的第一个NULL 后面还有其他指针,则它们将被忽略。拥有多个 NULL 听起来像是构建 argv 的程序中的错误。
    • 当指针数大于等于MAX_ARG_STRINGS时,即defined0x7FFFFFFF。在这种情况下,系统调用会失败。

    get_user_arg_ptr 返回时,i 返回的值被赋值给argc

    argv 中终止NULL 很重要的另一种情况是应用程序本身使用argv,如下所示:

    for(char **p = argv; *p != NULL; ++p)
    {
       // ...
    }
    

    argvNULL 结尾是 Linux ABI 的一部分,因此此类代码在所有 Linux 实现中都是合法且可移植的。顺便说一句,此代码在 Windows 上也是合法的。因此,提供argc 只是为了方便。

    此外,C 和 C++ 标准分别在 5.1.2.2.1 和 3.6.1 中规定,如果 argc 大于零,则 argv[0]argv[argc-1] 中的所有值都应为非-null 指向以 null 结尾的字符串的指针。 argv[argc] 也必须为 null 并且 argc 是非负数。另请参阅this 答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多