Mencioné "desbordamientos de búfer" en un comentario a la respuesta de Pythagras, probablemente debería aclarar un poco lo que quise decir. En C, no es suficiente saber que trabajar directamente con la memoria es peligroso; también debe comprender las formas precisas en que es peligroso. Realmente no me gusta la metáfora de "pegarse un tiro en el pie" para todos estos casos: muchas veces, no es que aprietas el gatillo, pero a menudo es un actor con intereses contrarios a los tuyos y / o de los usuarios .
Por ejemplo, en una arquitectura con una pila descendente (las arquitecturas más populares se ajustan a este proyecto de ley, generalmente se incluyen x86 y ARM), cuando se llama a una función, la dirección de retorno de la función se colocará en la pila después de las variables locales definidas en el cuerpo de la función. Entonces, si declara un búfer como una variable local y expone esa variable al mundo exterior sin verificar el desbordamiento del búfer, así:
void myFn(void) {
char buf[256];
gets(buf);
}
un usuario externo puede enviarle una cadena que sobrescribe la dirección de retorno de la pila; básicamente, puede cambiar la idea de tiempo de ejecución de su programa del gráfico de llamadas que conduce a la función actual. Entonces, el usuario le da una cadena que es la representación binaria de algún código ejecutable para su arquitectura, suficiente relleno para desbordar la pila myFn
y algunos datos adicionales para sobrescribir la dirección de retorno para myFn
que apunte al código que le dio. Si esto sucede, cuando myFn
normalmente hubiera devuelto el control a su interlocutor, en su lugar se ramificará al código que proporcionó el usuario malintencionado. Si escribe código C (o C ++) que tiene el potencial de exponerse a usuarios no confiables, debe comprender este vector de ataque. Debe comprender por qué un desbordamiento del búfer contra la pila es a menudo (pero no siempre) más fácilmente explotable que uno contra el montón, y debe comprender cómo se presenta la memoria en el montón (no con demasiados detalles, necesariamente, pero el La idea de que una malloc()
región ed tiene estructuras de control que la rodean puede ayudar a comprender por qué su programa se bloquea en otra malloc()
o en free()
).
C lo expone a detalles de bajo nivel sobre cómo funciona su máquina, y le brinda un control más directo sobre su máquina que cualquier otro lenguaje editado por el usuario en uso generalizado hoy en día. Con un gran poder viene una gran responsabilidad: realmente necesita comprender esos detalles de bajo nivel para trabajar con C de manera segura y efectiva.