The post Optimizaciones fatales appeared first on S3lab.
]]>int a, b, c; a = 10; b = a + 1; c = 0; printf(“a + b = %d\n”, a + b);
En este trozo de código, claramente la sentencia c = 0 sobra, y la variable c en sí es irrelevante. Un buen compilador daría un warning de que c no se usa, e internamente no produciría el código máquina equivalente a c = 0. Por otro lado, el siguiente código tiene un dead store y sí es necesario, aunque el compilador piense igualmente que el dead store debería eliminarse:
char *password = malloc(tamaño_password); // la aplicación lee la contraseña y hace alguna operación con ella... memset(password, 0, tamaño_passsword); free(password);
En este segundo ejemplo, aunque el memset parece inútil, tiene unas consideraciones de seguridad importantes, ya que si no escribiéramos ceros en las direcciones de la heap en las que password está almacenada, en el caso de que se diera algún error de memoria explotable en la aplicación, se podría leakear la contraseña. Si el compilador no quitase el dead store y hubiese una vulnerabilidad, la contraseña estaría protegida.
Evitar que se eliminen los dead stores no es una tarea fácil, ya que las aplicaciones que se usan en producción se suelen compilar con las optimizaciones habilitadas, porque se necesita que el código generado sea el óptimo. Algunas optimizaciones pueden depender de que previamente se limpie el código muerto, o simplemente se quiere eliminar el código muerto siempre, salvo en contadas excepciones.
Este problema aún sigue estudiándose, y no existe una solución multiplataforma universal para evitar que los dead stores se eliminen en casos concretos. Esto ha llevado a que los desarrolladores usen funciones específicas de su sistema operativo diseñadas tieniendo en cuenta estos problemas u ofusquen las operaciones de dead store para que el compilador no las entienda y no pueda optimizarlas (eliminarlas).
The post Optimizaciones fatales appeared first on S3lab.
]]>