stringtranslate.com

Código inalcanzable

En programación de computadoras , 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 ningún efecto en la salida de un programa. [4]

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

Sin embargo, el código inalcanzable 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 e imprimir 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 muchas razones, como por ejemplo:

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

Un ejemplo de dicho 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 usa un pequeño subconjunto. Normalmente, los compiladores 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 ) { retorno X + Y ; int Z = X * Y ; }               

la definición int Z = X * Y; nunca se alcanza ya que la función siempre regresa antes que él. Por lo tanto, no es necesario asignar almacenamiento a Z ni inicializarlo.

ir a fallar error

SSL/TLS de Apple de febrero de 2014 contenía un importante fallo de seguridad conocido formalmente como CVE - 2014-1266 e informalmente como "error de fallo de goto". [5] [6] El fragmento de código relevante [7] es:

OSStatus estático SSLVerifySignedServerKeyExchange ( SSLContext * ctx , bool isRsa , SSLBuffer firmadoParams , uint8_t * firma , UInt16 firmaLen ) { OSStatus err ; ... if (( err = SSLHashSHA1 . actualizar ( & hashCtx , & serverRandom )) ! = 0 ) ir a fallar ; if (( err = SSLHashSHA1 . actualizar ( & hashCtx , & firmadoParams )) ! = 0 ) ir a fallar ; ir a fallar ; if (( err = SSLHashSHA1 . final ( & hashCtx , & hashOut )) ! = 0 ) ir a fallar ; ... falla : SSLFreeBuffer ( y Hashes firmados ); SSLFreeBuffer ( & hashCtx ); devolver errar ; }                                                 

Aquí hay dos llamadas sucesivas a goto fail. En la sintaxis del lenguaje C, el segundo es incondicional y, por lo tanto, siempre omite la llamada a SSLHashSHA1.final. Como 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] La aplicación del compilador Clang con la opción -Weverythingincluye 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 es libre 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 de flujo de control para encontrar código al que nunca se podrá 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 de optimización (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 declaración if en el siguiente código es inalcanzable:

int norte = 2 + 1 ;     if ( 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 = raíz cuadrada ( 2 );   if ( 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 inactivo y la eliminación de código redundante .

Inalcanzabilidad versus elaboración de perfiles

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

Ver también

Referencias

  1. ^ Debray, Saumya K.; Evans, Guillermo; Muth, Robert; De Sutter, Bjorn (1 de marzo de 2000). "Técnicas de compilación para la compactación de código". Transacciones ACM sobre lenguajes y sistemas de programación . 22 (2): 378–415. CiteSeerX 10.1.1.43.7215 . doi :10.1145/349214.349233. S2CID  6129772. 
  2. ^ Consideraciones de software RTCA/DO-178C en la certificación de equipos y sistemas aerotransportados. RTCA, Inc. 2011. pág. 112 . Consultado el 11 de junio de 2019 . Código muerto: código objeto ejecutable (o datos) que existe como resultado de un error de desarrollo de software pero que no se puede ejecutar (código) ni utilizar (datos) en ninguna configuración operativa del entorno informático de destino. No es atribuible a un requisito del sistema o software. Las siguientes excepciones a menudo se clasifican erróneamente como código inactivo, pero son necesarias para la implementación de los requisitos/diseño: identificadores integrados, estructuras de programación defensivas para mejorar la solidez y código desactivado, como funciones de biblioteca no utilizadas. [Dado que la revisión basada en requisitos debería identificar dicho código como imposible de rastrear hasta los requisitos funcionales, el análisis de código estático debería identificar dicho código como inalcanzable, y el análisis de cobertura estructural de los resultados de las pruebas basadas en requisitos debería identificar dicho código como inalcanzable, la presencia de código muerto injustificado en un El 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 los requisitos constituye la base para pruebas exhaustivas de software" . Consultado el 11 de junio de 2019 . La combinación de trazabilidad de requisitos con 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 Directrices para el uso del lenguaje C en sistemas críticos. MIRA Limitada . pag. 41 . Consultado el 11 de junio de 2019 . Regla 2.2 no habrá código muerto . Cualquier operación que se ejecute pero cuya eliminación no afecte el comportamiento del programa constituye código muerto .
  5. ^ ab Adam Langley (2014). "Error de 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 admitir el intercambio de claves y el intercambio de claves del servidor".
  8. ^ "MSC15-C. No dependa de un comportamiento indefinido". Universidad de 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 optimización.
  9. ^ "Especificación del lenguaje Java".