¿Se puede desbordar argc?
integer-overflow (4)
Estaba vagando en SO y vi esta pregunta . Entonces comencé a preguntarme si puedo desbordar argc.
Standard dice que
argv[argc]
debe ser un puntero nulo, pero esto será falso si se desborda argc.
(
wrote
un pequeño programa en C y un script de Python para probarlo pero obtuve un
MemoryError
).
¡Gracias!
Justificación de la norma internacional - Lenguajes de programación - C §5.1.2.2.1 Inicio del programa
La especificación de
argc
yargv
como argumentos paramain
reconoce una práctica previa extensa. Se requiere queargv[argc]
sea un puntero nulo para proporcionar una verificación redundante para el final de la lista, también sobre la base de la práctica común.
De acuerdo a la norma
Entonces, de tu cita:
Se requiere
argv[argc]
para ser un puntero nulo
Por lo tanto,
argc
no puede desbordarse, porque la afirmación anterior no sería verdadera.
En la práctica
En la práctica, el tamaño total de los argumentos pasados a un programa es limitado.
En mi sistema Linux / x64:
$ getconf ARG_MAX 2097152
Por lo tanto, el tamaño total del argumento es de aproximadamente 2 megabytes, y
argc
no puede desbordarse.
Creo que este límite mide una combinación de los datos totales en
argv
y el entorno.
Si excede este límite cuando intenta ejecutar un comando,
exec()
fallará con
E2BIG
.
Del
man 2 execve
:
E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.
Creo que el límite de ~ 2 megabytes en mi sistema es relativamente generoso en comparación con otros sistemas. Mi sistema OS X informa un límite de ~ 260 KB.
Pero, ¿y si
ARG_MAX
fuera realmente grande?
De acuerdo, supongamos que está en un sistema antiguo / extraño, por lo que
int
tiene 16 bits y ARG_MAX tiene más de 2
15
, lo que es bastante razonable.
Ahora, suponga que invoca
execve()
con más de 2
15
argumentos.
La implementación tiene dos opciones.
-
Puede permitir que se desborde
argc
... básicamente, desechando sus datos, asegurando que el programa que está ejecutando se ejecute de manera inesperada y probablemente errónea, y violando el estándar C. Lo peor de todo, el error es silencioso, por lo que es posible que nunca sepas. -
O simplemente puede devolver
EOVERFLOW
deexecve()
, informándole que simplemente no puede ejecutar una imagen con tantos parámetros. Ahora, los estándares POSIX / SUS no mencionan nada acerca de este resultado de error ... pero, sospecho que esto es simplemente porque los escritores estándar nunca esperaron queARG_MAX
fuera más grande queINT_MAX
.
La opción # 2 es la única opción razonable. Si su sistema de alguna manera elige la opción # 1, entonces está roto y debe presentar un informe de error.
Alternativamente, podría estar intentando ejecutar un programa antiguo compilado para un sistema de 16 bits, pero lo está ejecutando a través de algún tipo de emulador o capa de compatibilidad. Esperaría que el emulador o la capa de compatibilidad emitieran un mensaje de error si intentara pasar más de 2 15 parámetros a un programa.
Como lo indica el estándar, argv [argc] debe ser un valor válido.
Entonces, si el entorno de tiempo de ejecución se encuentra en una situación tal que no puede garantizarlo, no debe iniciar el programa.
En la práctica, no, no puedes.
La mayoría de los sistemas establecen un límite relativamente bajo en el tamaño combinado total de
argv
y
envp
.
Los límites en las decenas a bajos cientos de KB no son infrecuentes;
ver
http://www.in-ulm.de/~mascheck/various/argmax/
para obtener una lista razonablemente completa de los límites en varios sistemas operativos.
Intenté esto:
prueba.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;
}
Luego usó un gran archivo zip
⚡⚡⚡ ls -h bigfile
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile
Luego lea el archivo como parámetros para el programa de prueba:
⚡⚡⚡ ./test $(more bigfile)
Resultado:
5 minutes nothing happend, then everything froze
Luego probé un archivo más pequeño:
⚡⚡⚡ ls -h notsobigfile
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile
Y:
⚡⚡⚡ ./test $(more notsobigfile)
bash: ./test: Argument list too long