stringtranslate.com

Código inalcanzable

En programación informática , el código inalcanzable es parte del código fuente de un programa que nunca puede ejecutarse porque no existe una ruta de flujo de control hacia el código desde el resto del programa. [1]

El código inalcanzable a veces también se denomina código muerto , [2] [3] aunque el código muerto también puede referirse al código que se ejecuta pero no tiene efecto en la salida de un programa. [4]

El código inaccesible generalmente se considera indeseable por varias razones:

El código inaccesible puede tener algunos usos legítimos, como proporcionar una biblioteca de funciones para llamar o saltar manualmente a través de un depurador mientras el programa se detiene después de un punto de interrupción . Esto es particularmente útil para examinar y escribir en formato de impresión el estado interno del programa. Puede tener sentido tener dicho código en el producto enviado, de modo que un desarrollador pueda adjuntar un depurador a la instancia en ejecución de un cliente.

Causas

El código inalcanzable puede existir por muchos motivos, como:

El código heredado es aquel que alguna vez fue útil pero que ya no se usa ni se requiere. Pero el código inaccesible también puede ser parte de una biblioteca, un módulo o una rutina complejos que son útiles para otros o en condiciones que no se cumplen en un escenario particular.

Un ejemplo de código condicionalmente inalcanzable puede ser la implementación de una función de formato de cadena general en la biblioteca de tiempo de ejecución de un compilador, que contiene código complejo para procesar todos los argumentos posibles, de los cuales solo se utiliza un pequeño subconjunto. Los compiladores normalmente no podrán eliminar las secciones de código no utilizadas en tiempo de compilación, ya que el comportamiento está determinado en gran medida por los valores de los argumentos en tiempo de ejecución.

Ejemplos

En este fragmento de código C:

int foo ( int X , int Y ) { devolver X + Y ; int Z = X * Y ; }               

La definición int Z = X * Y; nunca se alcanza porque la función siempre retorna antes que ella. Por lo tanto, no es necesario asignar espacio de almacenamiento a Z ni inicializarlo.

Ir al error de error

El SSL/TLS de Apple de febrero de 2014 contenía una importante falla de seguridad conocida formalmente como CVE - 2014-1266 e informalmente como el "error de error de Goto". [5] [6] El fragmento de código relevante [7] es:

estático OSStatus SSLVerifySignedServerKeyExchange ( SSLContext * ctx , bool isRsa , SSLBuffer signedParams , uint8_t * signature , UInt16 signatureLen ) { OSStatus err ; ... si (( err = SSLHashSHA1.update ( & hashCtx , & serverRandom )) != 0 ) ir a error ; si (( err = SSLHashSHA1.update ( & hashCtx , & signedParams )) != 0 ) ir a error ; ir a error ; si (( err = SSLHashSHA1.final ( & hashCtx , & hashOut ) ) ! = 0 ) ir a error ; ... error : SSLFreeBuffer ( & signedHashes ) ; SSLFreeBuffer ( & hashCtx ) ; devolver err ; }                                                 

Aquí hay dos goto faildeclaraciones sucesivas. En la sintaxis del lenguaje C, la segunda es incondicional y, por lo tanto, siempre omite la llamada a SSLHashSHA1.final. En consecuencia, errmantendrá el estado de la operación de actualización SHA1 y la verificación de la firma nunca fallará. [5]

Aquí, el código inalcanzable es la llamada a la finalfunción. [6] Al aplicar el compilador Clang-Weverything con la opción se incluye un análisis de código inalcanzable, lo que activaría una alarma para este código. [6]

C++

En C++ , se especifica que algunas construcciones tienen un comportamiento indefinido . Un compilador tiene la libertad de implementar cualquier comportamiento o ninguno, y normalmente un compilador optimizador asumirá que el código es inalcanzable. [8]

Análisis

La detección de código inalcanzable es una forma de análisis del flujo de control para encontrar código al que nunca se puede acceder en ningún estado posible del programa. En algunos lenguajes (por ejemplo, Java [9] ) algunas formas de código inalcanzable están explícitamente prohibidas. La optimización que elimina el código inalcanzable se conoce como eliminación de código muerto .

El código puede volverse inalcanzable como consecuencia de transformaciones realizadas por un compilador optimizador (por ejemplo, eliminación de subexpresiones comunes ).

En la práctica, la sofisticación del análisis tiene un impacto significativo en la cantidad de código inalcanzable que se detecta. Por ejemplo, el plegado constante y el análisis de flujo simple muestran que el interior de la instrucción if en el siguiente código es inalcanzable:

int N = 2 + 1 ;     si ( N == 4 ) { /* inalcanzable */ }    

Sin embargo, se necesita mucha más sofisticación para determinar que el bloque correspondiente es inalcanzable en el siguiente código:

doble X = sqrt ( 2 );   si ( X > 5 ) { /* inalcanzable */ }    

La técnica de eliminación de código inalcanzable pertenece a la misma clase de optimizaciones que la eliminación de código muerto y la eliminación de código redundante .

Inaccesibilidad vs. elaboración de perfiles

En algunos casos, un enfoque práctico puede ser una combinación de criterios de inaccesibilidad simples y el uso de un generador de perfiles para manejar los casos más complejos. El análisis de perfiles en general no puede probar nada sobre la inaccesibilidad de un fragmento de código, pero puede ser una buena heurística para encontrar código potencialmente inaccesible. Una vez que se encuentra un fragmento de código sospechoso, se pueden utilizar otros métodos, como una herramienta de análisis de código más potente, o incluso un análisis manual, para decidir si el código es realmente inaccesible.

Véase también

Referencias

  1. ^ Debray, Saumya K.; Evans, William; Muth, Robert; De Sutter, Bjorn (1 de marzo de 2000). "Técnicas de compilación para compactación de código". ACM Transactions on Programming Languages ​​and Systems . 22 (2): 378–415. CiteSeerX 10.1.1.43.7215 . doi :10.1145/349214.349233. S2CID  6129772. 
  2. ^ RTCA/DO-178C Consideraciones de software en la certificación de sistemas y equipos aerotransportados. RTCA, Inc. 2011. p. 112. Consultado el 11 de junio de 2019. Código muerto: código de objeto ejecutable (o datos) que existe como resultado de un error de desarrollo de software pero que no se puede ejecutar (código) ni usar (datos) en ninguna configuración operativa del entorno informático de destino. No se puede rastrear hasta un requisito de sistema o software. Las siguientes excepciones a menudo se clasifican por error como código muerto, pero son necesarias para la implementación de los requisitos/diseño: identificadores integrados, estructuras de programación defensiva para mejorar la solidez y código desactivado, como funciones de biblioteca no utilizadas. [Dado que la revisión basada en requisitos debe identificar dicho código como no rastreable hasta los requisitos funcionales, el análisis de código estático debe identificar dicho código como inalcanzable y el análisis de cobertura estructural de los resultados de pruebas basadas en requisitos debe identificar dicho código como inalcanzable, la presencia de código muerto injustificado en un proyecto debe plantear la consideración de la eficacia de los procesos de desarrollo y verificación de la organización.]
  3. ^ Jay Thomas (24 de enero de 2017). "La trazabilidad de requisitos forma la base para una prueba de software exhaustiva" . Consultado el 11 de junio de 2019. La combinación de la trazabilidad de requisitos con el análisis de cobertura también puede revelar áreas de "código muerto", o código que nunca se ejecuta. Este código puede ser principalmente un inconveniente, pero también puede ser una amenaza para la seguridad si un pirata informático puede obtener acceso y, desde allí, obtener el control. Es un código que no se puede rastrear y, por lo tanto, debe eliminarse.
  4. ^ Consorcio MISRA (marzo de 2013). MISRA C:2012 Pautas para el uso del lenguaje C en sistemas críticos. MIRA Limited . p. 41 . Consultado el 11 de junio de 2019 . Regla 2.2 no debe haber código muerto . Cualquier operación que se ejecute pero cuya eliminación no afecte el comportamiento del programa constituye código muerto .
  5. ^ por Adam Langley (2014). "El error SSL/TLS de Apple".
  6. ^ abc Arie van Deursen (2014). "Aprendiendo del error de seguridad #gotofail de Apple".
  7. ^ "sslKeyExchange.c - Código fuente para soporte para intercambio de claves e intercambio de claves de servidor".
  8. ^ "MSC15-C. No depender de comportamientos indefinidos". Universidad Carnegie Mellon. 2020. Consultado el 28 de septiembre de 2020. Debido a que los compiladores no están obligados a generar código para comportamientos indefinidos, estos comportamientos son candidatos para la optimización.
  9. ^ "Especificación del lenguaje Java".