Un tema importante que no se cubrió en la respuesta de Evan es el número entero de desbordamientos.He aquí algunos ejemplos:
wchar_t *towcs(const char *s)
{
size_t l = strlen(s)+1;
mbstate_t mbs = {0};
wchar_t *w = malloc(l*sizeof *w), *w2;
if (!w || (l=mbsrtowcs(w, (char **)&s, l, &st))==-1) {
free(w);
return 0;
}
return (w2=realloc(w, l*sizeof *w)) ? w2 : w;
}
Aquí, una cadena gigante (> 1gig de 32 bits) hará que la multiplicación por el tamaño (estoy asumiendo 4) de desbordamiento, lo que resulta en una pequeña asignación y posteriores escrituras en el pasado fin de eso
Otro ejemplo más común:
uint32_t cnt;
fread(&cnt, 1, 4, f);
cnt=ntohl(cnt);
struct record *buf = malloc(cnt * sizeof *buf);
Este tipo de código se convierte en la lectura de datos de archivos/red mucho, y es objeto de la misma clase de desbordamientos.
Básicamente, cualquier aritmética realizada en valores obtenidos de una fuente que no es de confianza, que eventualmente se utilizará como un tamaño de asignación/desplazamiento de matriz, necesita ser verificada. Usted puede hacerlo de la manera barata (imponer límites arbitrarios en el valor de lectura que lo mantienen significativamente fuera del rango que podría desbordarse, o puede probar de desbordamiento en cada paso: En lugar de:
foo = malloc((x+1)*sizeof *foo);
Es necesario hacer:.
if (x<=SIZE_MAX-1 && x+1<=SIZE_MAX/sizeof *foo) foo = malloc((x+1)*sizeof *foo);
else goto error;
Un grep simple para malloc/realloc con los operadores aritméticos en su argumento encontrarán muchos de estos errores (pero no aquellos en los que se produjo el desbordamiento ya unas pocas líneas anteriores, etc.)
@Evan Teran Muchas gracias. También me gustaría saber cómo encontrar defectos de denegación de servicio – mousey
Los ataques DoS pueden ser causados por una serie de problemas diferentes. Pueden ser bloqueos, errores de lógica, fallas o simplemente tener un diseño que se sobrepasa con facilidad. Por ejemplo, hacer que un servidor use un hilo por socket de cliente a menudo puede ser DoS'd simplemente porque no se escala bien en muchos sistemas operativos. –
O incluso más simple, el uso de sockets de bloqueo sin límite de tiempo o límite de caracteres puede permitir que un DoSer mantenga activa la conexión y agote lentamente todos los sockets disponibles. En realidad, hay muchísimas formas de ser atacado: - /. –