2011-01-04 8 views
15

Estoy trabajando en un proyecto grande que generalmente funciona bien, pero muestra serios problemas una vez que el tamaño de los datos de entrada excede algunas limitaciones.¿Cómo encontrar (todos) desbordamientos de enteros en un programa C?

Estas cuestiones son (se sospecha) sólo se debe a desbordamientos de entero con signo como éstos:

int a, o; 
// Initialize a and o 
int x = (a+o) >> 1); 

Obviamente, una vez que la suma de a y o desbordamientos (se hace más grande que 2^31-1), x es sin más largo la media de a y o.

¿Existe alguna manera genérica de encontrar todos estos desbordamientos de enteros en un programa en ejecución?

Estoy pensando en una herramienta como Valgrind o una extensión GDB que se rompe en cada instrucción aritmética entera, toma los parámetros y compara el resultado correcto (calculado con un tipo de datos de mayor tamaño o aritmética de precisión arbitraria) con el resultado real . Si los resultados difieren, debe emitir una advertencia, desencadenar una interrupción de depuración o algo así.

Sé, cómo verificar una sola instrucción aritmética para desbordamientos (por ejemplo, revisar el signo para adiciones), sin embargo, debido a la gran cantidad de código, no es una solución viable para mí pasar por todo el proyecto e insertar la verificación código en todas partes a mano.

Respuesta

3

Para gran base de código, Coverity es un buen herramienta. No estoy seguro de que detecte desbordamientos enteros all o no, pero vale la pena intentarlo.

2

Tiene que trabajar con todo el código y determinar cuál es el límite en la entrada del usuario y validar la entrada. Es posible que también necesite volver a escribir algunos algoritmos para reducir los problemas de desbordamiento.

Como el ejemplo que proporciona no funciona para los valores negativos, debe utilizar un unsigned int de todos modos, lo que le da un orden adicional de magnitud ya.

Editar: gcc tiene la opción -ftrapv, pero esto por lo general no hace nada sólo funciona con -O0. Si está tomando el enfoque de atrapar desbordamientos cuando suceden, aún necesita un buen conocimiento del código para poder probarlo por completo.

+0

Más o menos sé cuál es el límite de la entrada del usuario. El problema al trabajar con el código es que el proyecto tiene más de 200k líneas (199k de ellas no están escritas por mí) y me temo que sería muy difícil verificarlas a mano en busca de un código propenso al desbordamiento. – ChrisM

+0

@ChrisM: si estás en una posición en la que no puedes confiar en que el código que alguien más escribió es correcto, entonces probablemente no deberías usarlo. Las prácticas comerciales deben estar en su lugar para tratar con cosas como esta (revisiones, pruebas, etc.). Si eres solo tú con este código y nadie más a tu alrededor, vas a necesitar pasar algún tiempo leyendo todo de todos modos. – OrangeDog

+0

Bien, es una pena. Solo esperaba que hubiera una manera de encontrar las secciones problemáticas en el código (probablemente una docena, o más) automáticamente. – ChrisM

0

¿Qué tal un script que va a través del código y sustituye a todos "a + b" con DEBUGADD (a, b) - donde se puede hacer:

#ifdef DEBUG 
int addFn(int a, int b) { 
    long long m; 
    int n; 
    m = (long long)a + (long long)b; 
    n = a + b; 
    if (m != (long long)n) 
    printf("PANIC!\n"); 
    return n; 
} 
#define DEBUGADD(a,b) addFn(a,b) 
#else 
#define DEBUGADD(a,b) ((a)+(b)) 
#endif 
+3

Solo asegúrese de que su secuencia de comandos maneja el espacio en blanco, los moldes, el orden de las operaciones y los tipos de devolución correctamente :) – Karmastan

+0

Mejor sería simplemente 'assert (((a <= 0) || (b <= INT_MAX - a)) && ((a> = 0) || (b> = INT_MIN - a))) ', ya que una expresión similar también funcionará para' long' y 'long long'. – caf

Cuestiones relacionadas