2009-11-04 12 views
5

Estoy en una situación en la que estoy obligado a hacer al menos un esfuerzo para eliminar el código nunca utilizado de mi código fuente. La preferencia general es usar una herramienta de análisis de código estático. Hemos tenido una gran suerte con esto en otros proyectos, pero la gente de la que escucho son en su mayoría desarrolladores de C/C++ que trabajan en el código de nivel de dispositivo.¿Qué tan bien funciona el análisis de código estático con Spring y otras abstracciones?

Soy un desarrollador web que trabaja en un sistema Java EE. La herramienta favorita para el análisis es Coverity Prevent, aunque probablemente podría abogar por otra cosa si pudiera defender que era más apropiado para la tecnología con la que estamos desarrollando.

Me resulta dudoso: ¿qué efecto tiene el análisis de código estático para el código muerto, cuando se está ejecutando contra un sistema con muchas abstracciones? Por ejemplo, utilizamos la inyección de dependencia Spring, así como JSF. En ambos casos, no hay una manera fácil de rastrear a través de las llamadas a función desde el frente hasta el final y hacer una imagen completa de lo que se llama y lo que no.

Estoy muy preocupado de que los falsos positivos en una verificación de código muerto superen el valor de ejecutar la herramienta en primer lugar.

¿Cuál es la experiencia con este escenario? ¿Logró obtener valor de una herramienta de análisis de código estático cuando su arquitectura usó muchas abstracciones? ¿Hubo algo que tuviera que hacer para que funcione con un mínimo de falsos positivos?

+0

Esto parece más una pregunta de wiki de comunidad. –

Respuesta

4

Anteriormente trabajé en Coverity, en el producto de análisis estático de Java.

Esta tarea particular de encontrar el código muerto puede ser impredecible para un analizador estático. Para los métodos muertos en particular, lo que significa un método que no se puede invocar en tiempo de ejecución, la tasa de falsos positivos será muy alta sin una gran afinación para informar al analizador estático acerca de todos los puntos de entrada dinámicos.

Para código muerto dentro de un método, si su analizador tiene esa capacidad, los resultados deberían ser bastante buenos, ya que el análisis no hará suposiciones sobre los datos de entrada. Incluso asumiendo todas las entradas posibles, es posible encontrar un código muerto donde la lógica correlacionada impide que se tomen ciertas ramas.

0

El análisis del código estático en todos los casos solo debe realizarse si comprende completamente el proceso de análisis y el código. El problema simplemente es que es simplemente difícil y ofrece suposiciones. Ni una solución, ni una verificación completamente precisa de las vulnerabilidades. Tienes que poder determinar los falsos positivos con otros métodos de prueba.

El valor de un analizador de código estático no es una revisión de código. Para eliminar el código muerto usaría la cobertura de código para perfilar eso. - En tu caso, mencionaste muchas abstracciones ... Creo que el análisis del código estático no será suficiente.

+1

Esto parece un consejo terriblemente estricto. Entonces, ¿nadie debería usar Findbugs a menos que comprenda los límites de un análisis de flujo de datos? El producto de Coverity no está permitido hasta que haya leído los detalles de la interpretación abstracta. Si te gustan los resultados, ve con él. No es necesario entender exactamente cómo se hace el análisis. –

+0

Pero eso es exactamente lo que quise decir: nadie debería usar FindBugs, PMD ni nada relacionado con el análisis de código estático a menos que esté familiarizado con el análisis de flujo de datos. De lo contrario, las personas tienden a tratar de evitar la detección, pero producen los mismos errores de todos modos. Solo los programadores más sofisticados pueden usar el análisis de código estático de manera eficiente para eliminar vulnerabilidades en el código. El producto que encuentra el problema no escribe un parche ni conoce el modelo. – wishi

2

Puede usar las herramientas de cobertura de prueba (análisis dinámico) para determinar qué código de su sistema es usado; el complemento es un código que podría estar muerto (¡no se ejecutó!) y necesita inspección (por ejemplo, puede haber algunos falsos positivos). Cuanto más ejercicio le dé a su sistema, menor será la tasa de falsos positivos.

Una herramienta de cobertura de prueba de Java que puede recopilar esta información para usted se puede encontrar here.

Si desea minimizar los falsos positivos, puede considerar ejecutar la herramienta de análisis estático y probar la cobertura, y tomar la intersección.

En general, detectar el código muerto X requiere probar que no hay ninguna condición bajo la cual se invoca X. Eso es difícil (teóricamente imposible) cuando se enfrentan a una máquina de Turing y SI enunciados de la forma

if (Turing(..)) then call X(); 

por lo que las herramientas de análisis estático tienen altas tasas de falsos positivos para esto.

En muchos casos, sin embargo, el "código muerto" es realmente un código que simplemente no tiene forma de invocarlo ("código de desactivación" en el lenguaje FAA). Es decir, mientras que X se define, simplemente no hay invocaciones de X (o accesos, si X es un elemento de datos) en cualquier parte del sistema, directa o indirectamente. Son más fáciles de detectar para las herramientas de análisis estático con la compleja complicación en Java de la carga y reflexión dinámica de clases (que hace que el problema del análisis de códigos desactivadores sea imposible frente a clases desconocidas pero cargables).

Ignorando estas complicaciones, se pueden encontrar herramientas de análisis estático que detectan el código de desactivación en grandes sistemas Java y lo informan. Tal herramienta tiene que procesar todo el sistema Java a la vez porque, de lo contrario, podría existir una referencia en el único módulo no incluido en el análisis. Hemos creado un "deactive" code detector and remover que incluso puede proporcionarle su código fuente con todo el código desactivo eliminado automáticamente, así como informar sobre lo que no se referencia. Inspecciona el informe y decide si deseas utilizar el código limpio o agregar un acceso a una entidad aparentemente no utilizada.

+0

Las teorías de imposibilidad sobre los programas están sobredimensionadas cuando se trata de herramientas de análisis estático. El problema de la detención es un gran problema, como se menciona en el método de Turing(), pero se aplica a la optimización de los compiladores, y nadie duda de la utilidad de un compilador de optimización. Las herramientas de análisis deben proporcionar evidencia al usuario, y los usuarios no creerán una cadena compleja de evidencia. Esto deja lo relativamente mundano, pero eso es interesante ya que una herramienta puede encontrar problemas, ya que son muy dispares en la base de códigos, que sería muy difícil de identificar para un humano, pero son bastante fáciles de verificar para un ser humano. –

+0

No estoy fallando en las herramientas de análisis estático (¡yo también las valoré!), Simplemente observando que la teoría garantiza que no pueden producir la respuesta correcta en todas las circunstancias. Estoy de acuerdo en que la respuesta correcta es utilizar las herramientas de análisis estático porque son mucho mejores en generatl para tratar la complejidad que las personas, pero para verificar las respuestas. "Confiar pero verificar". –

1

Trabajando en análisis estático, no conozco ninguna herramienta de análisis estático que realmente funcione con abstracciones. Lo más probable es que tenga que escribir un módulo que se enganche en el proceso de análisis y las razones sobre la forma en que utiliza las abstracciones.

Y dudo que la presencia de código muerto cueste más que esto.

Cuestiones relacionadas