C-可以将数组用作最后一个命名参数到variadic函数导致缓冲区底部的函数



我在 stdarg.h的男人页面中找到了此段落:

由于此参数的地址在va_start((宏中使用,因此不应将其声明为寄存器变量,也不应为函数或数组类型。

因此,我了解的注册变量,因为无法用指针处理寄存器。我了解的功能,因为您将获得返回值,它将使用立即地址而不是地址寄存器间接地址。

我很好奇如果您使用数组作为参数会发生什么。假设您使用三种int类型的数组。这将导致数组的第一个元素用作最后一个命名参数,而接下来的两个元素最终将被用作变量参数的值?这将是一个缓冲区底层。

我也想知道这是否会导致安全漏洞,例如有人可以输入数组的元素,并让函数执行不应该做的事情,因为它认为额外的数组元素是可变参数。

另外,printf功能系列呢?这些使用字符数组作为他们的最后一个命名参数。他们如何不遇到问题?

这看起来像是男人页面中的错误。

function 不能具有数组类型函数类型的参数,因为任何数组声明作为函数参数都会转换为指针,函数的参数也是如此类型。

C标准详细函数声明器的第6.7.6.3节指定以下内容:

7 参数的声明为"类型数组",应调整为"合格指针" ,其中类型的预选赛(如果有(为 在数组类型派生的[和]中指定的那些。如果 关键字静态也出现在数组类型的[和]中 派生,然后对于每个呼叫函数的呼叫, 相应的实际论点应提供第一个访问权限 数组的元素,至少具有与该数组一样多的元素 尺寸表达式。

8 参数的声明为"函数返回类型",应将其调整为"函数返回类型的指针" ,例如6.3.2.1

因此,就 va_start而言,这意味着最后一个命名参数不能使用 register指示符。阵列和功能无关紧要,因为它们已调整为指针。

您正在想象逐个值,这不会发生。

数组和函数作为地址传递。

我怀疑在某些编译器中,sizeof((返回(或返回一次(数组的大小,而不是指向第一个元素的指针的大小。我不确定功能。

此代码:

#include <stdio.h>
void test(void (*f)(), int a[3]) {
    printf("sizeof(f): %lun", sizeof(f));
    printf("sizeof(a): %lun", sizeof(a));
    printf(" f: %pn", f);
    printf("&f: %pn", &f);
    printf(" a: %pn", a);
    printf("&a: %pn", &a);
}
void foo() {}
int main() {
    int ints[3] = { 1, 2, 3 };
    test(foo, ints);
}

当我用GCC编译时,请给我这个警告:

address.c: In function ‘test’:
address.c:6:38: warning: ‘sizeof’ on array function parameter ‘a’ will return size of ‘int *’ [-Wsizeof-array-argument]
     printf("sizeof(a): %lun", sizeof(a));
                                      ^
address.c:4:28: note: declared here
 void test(void (*f)(), int a[3]) {
                            ^

这似乎意味着编译器作者怀疑程序员可能会对这是什么感到困惑,因此编译器作家之间也可能存在(或曾经(分歧。

如果sizeof((是返回数组的大小,而不是堆栈上传递的指针的大小,则可能导致va_start/va_arg在寻找下一个参数时跳过错误的字节。<<<<<<<<<<<<<<<<<<<<<<<<<<

相关内容

  • 没有找到相关文章

最新更新