argc 会溢出吗?
Can argc overflow?
我在SO里闲逛,看到了this question。然后就开始想能不能溢出argc。
标准规定 argv[argc]
必须是一个空指针,但如果 argc 溢出,这将是错误的。
(我 wrote 一个小的 C 程序和一个 python 脚本来测试它但是得到了一个 MemoryError
。)
谢谢!
Rationale for International Standard — Programming Languages — C §5.1.2.2.1 Program startup
The specification of argc
and argv
as arguments to main
recognizes extensive prior practice. argv[argc]
is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.
在实践中,不,你不能。大多数系统对 argv
和 envp
的总组合大小设置了相对较低的限制。几十到几百 KB 的限制并不少见。有关各种操作系统限制的相当全面的列表,请参阅 http://www.in-ulm.de/~mascheck/various/argmax/。
按照标准
因此,根据您的引述:
argv[argc]
is required to be a null pointer
因此,argc
不能溢出,因为那样上面的说法就不成立了。
在实践中
实际上,传递给程序的参数的总大小是有限的。
在我的 Linux/x64 系统上:
$ getconf ARG_MAX
2097152
因此,总参数大小约为2MB,argc
不能溢出。我相信这个限制衡量的是 argv
中的总数据和环境的组合。如果在尝试 运行 命令时超过此限制,exec()
将失败并返回 E2BIG
。来自 man 2 execve
:
E2BIG The total number of bytes in the environment (envp) and argument
list (argv) is too large.
我相信与其他系统相比,我系统的 ~2 兆字节限制相对宽松。我的 OS X 系统报告限制为 ~260KB。
但是如果 ARG_MAX
真的很大呢?
好吧,假设你在 old/weird 系统上,所以 int
是 16 位,而 ARG_MAX 远远超过 215,这在其他方面是相当合理的。现在,假设您使用超过 215 个参数调用 execve()
。实现有两个选项。
它可以让 argc
溢出...基本上,扔掉你的数据,确保你正在 运行ning 的程序在一些意外的和可能错误的情况下执行方式,并且违反了 C 标准。最糟糕的是,错误是无声的,因此您可能永远不会知道。
或者,它可以简单地从 execve()
return EOVERFLOW
,告诉你它根本无法 运行 一个图像有那么多参数。现在,POSIX / SUS 标准没有提及任何关于这个错误结果的信息......但是,我怀疑这仅仅是因为标准编写者从未预料到 ARG_MAX
会大于 INT_MAX
.
选项#2 是唯一 合理的选项。如果您的系统以某种方式选择了选项 #1,那么它 已损坏 ,您应该提交错误报告。
或者,您可以尝试 运行 为 16 位系统编译的旧程序,但您 运行 通过某种仿真器或兼容层对其进行编译。如果您尝试将超过 215 个参数传递给程序,我希望仿真器或兼容层会给出错误消息。
我试过这个:
test.c :
⚡⚡⚡ more test.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("argc = %d\n", argc);
printf("Size of argc = %d\n", sizeof(argc));
return 0;
}
然后用了一个大zip文件
⚡⚡⚡ ls -h bigfile
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile
然后读取文件作为参数给测试程序:
⚡⚡⚡ ./test $(more bigfile)
结果:
5 minutes nothing happend, then everything froze
然后我尝试了一个较小的文件:
⚡⚡⚡ ls -h notsobigfile
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile
并且:
⚡⚡⚡ ./test $(more notsobigfile)
bash: ./test: Argument list too long
根据标准,argv[argc] 必须是有效值。
所以如果运行-时间环境处于无法保证的情况下,则不应启动程序。
我在SO里闲逛,看到了this question。然后就开始想能不能溢出argc。
标准规定 argv[argc]
必须是一个空指针,但如果 argc 溢出,这将是错误的。
(我 wrote 一个小的 C 程序和一个 python 脚本来测试它但是得到了一个 MemoryError
。)
谢谢!
Rationale for International Standard — Programming Languages — C §5.1.2.2.1 Program startup
The specification of
argc
andargv
as arguments tomain
recognizes extensive prior practice.argv[argc]
is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.
在实践中,不,你不能。大多数系统对 argv
和 envp
的总组合大小设置了相对较低的限制。几十到几百 KB 的限制并不少见。有关各种操作系统限制的相当全面的列表,请参阅 http://www.in-ulm.de/~mascheck/various/argmax/。
按照标准
因此,根据您的引述:
argv[argc]
is required to be a null pointer
因此,argc
不能溢出,因为那样上面的说法就不成立了。
在实践中
实际上,传递给程序的参数的总大小是有限的。
在我的 Linux/x64 系统上:
$ getconf ARG_MAX 2097152
因此,总参数大小约为2MB,argc
不能溢出。我相信这个限制衡量的是 argv
中的总数据和环境的组合。如果在尝试 运行 命令时超过此限制,exec()
将失败并返回 E2BIG
。来自 man 2 execve
:
E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.
我相信与其他系统相比,我系统的 ~2 兆字节限制相对宽松。我的 OS X 系统报告限制为 ~260KB。
但是如果 ARG_MAX
真的很大呢?
好吧,假设你在 old/weird 系统上,所以 int
是 16 位,而 ARG_MAX 远远超过 215,这在其他方面是相当合理的。现在,假设您使用超过 215 个参数调用 execve()
。实现有两个选项。
它可以让
argc
溢出...基本上,扔掉你的数据,确保你正在 运行ning 的程序在一些意外的和可能错误的情况下执行方式,并且违反了 C 标准。最糟糕的是,错误是无声的,因此您可能永远不会知道。或者,它可以简单地从
execve()
returnEOVERFLOW
,告诉你它根本无法 运行 一个图像有那么多参数。现在,POSIX / SUS 标准没有提及任何关于这个错误结果的信息......但是,我怀疑这仅仅是因为标准编写者从未预料到ARG_MAX
会大于INT_MAX
.
选项#2 是唯一 合理的选项。如果您的系统以某种方式选择了选项 #1,那么它 已损坏 ,您应该提交错误报告。
或者,您可以尝试 运行 为 16 位系统编译的旧程序,但您 运行 通过某种仿真器或兼容层对其进行编译。如果您尝试将超过 215 个参数传递给程序,我希望仿真器或兼容层会给出错误消息。
我试过这个:
test.c :
⚡⚡⚡ more test.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("argc = %d\n", argc);
printf("Size of argc = %d\n", sizeof(argc));
return 0;
}
然后用了一个大zip文件
⚡⚡⚡ ls -h bigfile
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile
然后读取文件作为参数给测试程序:
⚡⚡⚡ ./test $(more bigfile)
结果:
5 minutes nothing happend, then everything froze
然后我尝试了一个较小的文件:
⚡⚡⚡ ls -h notsobigfile
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile
并且:
⚡⚡⚡ ./test $(more notsobigfile)
bash: ./test: Argument list too long
根据标准,argv[argc] 必须是有效值。
所以如果运行-时间环境处于无法保证的情况下,则不应启动程序。