Ejecución simbólica - Symbolic execution

En informática , la ejecución simbólica (también evaluación simbólica o symbex ) es un medio de analizar un programa para determinar qué entradas hacen que se ejecute cada parte de un programa . Un intérprete sigue el programa, asumiendo valores simbólicos para las entradas en lugar de obtener entradas reales como lo haría la ejecución normal del programa. Por tanto, llega a expresiones en términos de esos símbolos para expresiones y variables en el programa, y ​​restricciones en términos de esos símbolos para los posibles resultados de cada rama condicional. Finalmente, las posibles entradas que desencadenan una rama se pueden determinar resolviendo las restricciones.

El campo de la simulación simbólica aplica el mismo concepto al hardware. La computación simbólica aplica el concepto al análisis de expresiones matemáticas.

Ejemplo

Considere el programa siguiente, que lee un valor y falla si la entrada es 6.

int f() {
  ...
  y = read();
  z = y * 2;
  if (z == 12) {
    fail();
  } else {
    printf("OK");
  }
}

Durante una ejecución normal (ejecución "concreta"), el programa leería un valor de entrada concreto (por ejemplo, 5) y se lo asignaría y. A continuación, la ejecución procedería con la multiplicación y la rama condicional, que se evaluaría como falso y se imprimiría OK.

Durante la ejecución simbólica, el programa lee un valor simbólico (por ejemplo, λ) y se lo asigna y. A continuación, el programa procedería con la multiplicación y asignaría λ * 2a z. Al llegar al ifenunciado, evaluaría λ * 2 == 12. En este punto del programa, λpodría tomar cualquier valor, por lo que la ejecución simbólica puede avanzar a lo largo de ambas ramas, "bifurcando" dos caminos. A cada ruta se le asigna una copia del estado del programa en la instrucción de bifurcación, así como una restricción de ruta. En este ejemplo, la restricción de ruta es λ * 2 == 12para la thenrama y λ * 2 != 12para la elserama. Ambos caminos se pueden ejecutar simbólicamente de forma independiente. Cuando las rutas terminan (por ejemplo, como resultado de la ejecución fail()o simplemente de salir), la ejecución simbólica calcula un valor concreto para λresolver las restricciones de ruta acumuladas en cada ruta. Estos valores concretos pueden considerarse casos de prueba concretos que pueden, por ejemplo, ayudar a los desarrolladores a reproducir errores. En este ejemplo, el solucionador de restricciones determinaría que para llegar a la fail()declaración, λnecesitaría ser igual a 6.

Limitaciones

Explosión de camino

La ejecución simbólica de todas las rutas de programa factibles no se escala a programas grandes. El número de rutas factibles en un programa crece exponencialmente con un aumento en el tamaño del programa e incluso puede ser infinito en el caso de programas con iteraciones de bucle ilimitado. Las soluciones al problema de la explosión de la ruta generalmente utilizan heurísticas para la búsqueda de rutas para aumentar la cobertura del código, reducir el tiempo de ejecución paralelizando rutas independientes o fusionando rutas similares.

Eficiencia dependiente del programa

La ejecución simbólica se usa para razonar sobre un programa ruta por ruta, lo cual es una ventaja sobre el razonamiento sobre un programa entrada por entrada como lo usan otros paradigmas de prueba (por ejemplo , análisis dinámico de programas ). Sin embargo, si pocas entradas toman el mismo camino a través del programa, hay pocos ahorros al probar cada una de las entradas por separado.

Alias ​​de memoria

La ejecución simbólica es más difícil cuando se puede acceder a la misma ubicación de memoria a través de diferentes nombres ( aliasing ). El alias no siempre se puede reconocer de forma estática, por lo que el motor de ejecución simbólica no puede reconocer que un cambio en el valor de una variable también cambia la otra.

Matrices

Dado que una matriz es una colección de muchos valores distintos, los ejecutores simbólicos deben tratar la matriz completa como un valor o tratar cada elemento de la matriz como una ubicación separada. El problema de tratar cada elemento de la matriz por separado es que una referencia como "A [i]" sólo se puede especificar dinámicamente, cuando el valor de i tiene un valor concreto.

Interacciones ambientales

Los programas interactúan con su entorno realizando llamadas al sistema , recibiendo señales, etc. Pueden surgir problemas de coherencia cuando la ejecución llega a componentes que no están bajo el control de la herramienta de ejecución simbólica (por ejemplo, kernel o bibliotecas). Considere el siguiente ejemplo:

int main()
{
  FILE *fp = fopen("doc.txt");
  ...
  if (condition) {
    fputs("some data", fp);
  } else {
    fputs("some other data", fp);
  }
  ...
  data = fgets(..., fp);
}

Este programa abre un archivo y, según alguna condición, escribe diferentes tipos de datos en el archivo. Luego, luego vuelve a leer los datos escritos. En teoría, la ejecución simbólica bifurcaría dos rutas en la línea 5 y cada ruta a partir de ahí tendría su propia copia del archivo. Por lo tanto, la declaración en la línea 11 devolvería datos que son consistentes con el valor de "condición" en la línea 5. En la práctica, las operaciones de archivo se implementan como llamadas al sistema en el kernel y están fuera del control de la herramienta de ejecución simbólica. Los principales enfoques para abordar este desafío son:

Ejecución de llamadas al entorno directamente. La ventaja de este enfoque es que es fácil de implementar. La desventaja es que los efectos secundarios de tales llamadas afectarán a todos los estados administrados por el motor de ejecución simbólica. En el ejemplo anterior, la instrucción en la línea 11 devolvería "algunos datos, algunos otros datos" o "algunos otros datos, algunos datos", según el orden secuencial de los estados.

Modelando el medio ambiente. En este caso, el motor instrumenta las llamadas del sistema con un modelo que simula sus efectos y que mantiene todos los efectos secundarios en el almacenamiento por estado. La ventaja es que se obtendrían resultados correctos al ejecutar simbólicamente programas que interactúan con el entorno. La desventaja es que es necesario implementar y mantener muchos modelos potencialmente complejos de llamadas al sistema. Herramientas como KLEE, Cloud9 y Otter adoptan este enfoque al implementar modelos para operaciones del sistema de archivos, sockets, IPC , etc.

Bifurcando todo el estado del sistema. Las herramientas de ejecución simbólica basadas en máquinas virtuales resuelven el problema del entorno mediante la bifurcación de todo el estado de la máquina virtual. Por ejemplo, en S2E, cada estado es una instantánea de VM independiente que se puede ejecutar por separado. Este enfoque alivia la necesidad de escribir y mantener modelos complejos y permite que prácticamente cualquier programa binario se ejecute simbólicamente. Sin embargo, tiene una mayor sobrecarga de uso de memoria (las instantáneas de VM pueden ser grandes).

Instrumentos

Herramienta Objetivo URL ¿Alguien puede usarlo / código abierto / descargable?
enojo basado en libVEX (compatible con x86, x86-64, ARM, AARCH64, MIPS, MIPS64, PPC, PPC64 y Java) http://angr.io/
BE-PUM x86 https://github.com/NMHai/BE-PUM
BINSEC x86, ARM, RISC-V (32 bits) http://binsec.github.io
crisol LLVM, JVM, etc. https://github.com/GaloisInc/crucible
Exponer JavaScript https://github.com/ExpoSEJS/ExpoSE
FuzzBALL VineIL / Nativo http://bitblaze.cs.berkeley.edu/fuzzball.html
Jalangi2 JavaScript https://github.com/Samsung/jalangi2
janala2 Java https://github.com/ksen007/janala2
JaVerT JavaScript https://www.doc.ic.ac.uk/~pg/publications/FragosoSantos2019JaVerT.pdf
JBSE Java https://github.com/pietrobraione/jbse
jCUTE Java https://github.com/osl/jcute
JPF Java http://babelfish.arc.nasa.gov/trac/jpf
Llave Java http://www.key-project.org/
cometa LLVM http://www.cs.ubc.ca/labs/isd/Projects/Kite/
KLEE LLVM https://klee.github.io/
Kudzu JavaScript http://webblaze.cs.berkeley.edu/2010/kudzu/kudzu.pdf no
MPro Máquina virtual Ethereum (EVM) / Nativa https://sites.google.com/view/smartcontract-analysis/home
Mantícora x86-64, ARMv7, Ethereum Virtual Machine (EVM) / Nativo https://github.com/trailofbits/manticore/
Violencia Binario http://forallsecure.com no
Mythril-Clásico Máquina virtual Ethereum (EVM) / Nativa https://github.com/ConsenSys/mythril-classic
Nutria C https://bitbucket.org/khooyp/otter/overview
Oyente-NG Máquina virtual Ethereum (EVM) / Nativa http://www.comp.ita.br/labsca/waiaf/papers/RafaelShigemura_paper_16.pdf no
Pathgrind Basado en Valgrind nativo de 32 bits https://github.com/codelion/pathgrind
Pex .NET Framework http://research.microsoft.com/en-us/projects/pex/ no
pysymemu x86-64 / Nativo https://github.com/feliam/pysymemu/
Rosetón Dialecto de la raqueta https://emina.github.io/rosette/
Rubyx Rubí http://www.cs.umd.edu/~avik/papers/ssarorwa.pdf no
S2E x86, x86-64, ARM / User y binarios en modo kernel http://s2e.systems/
PathFinder simbólico (SPF) Código de bytes de Java https://github.com/SymbolicPathFinder
SymDroid Código de bytes de Dalvik http://www.cs.umd.edu/~jfoster/papers/symdroid.pdf no
SymJS JavaScript https://core.ac.uk/download/pdf/24067593.pdf no
Tritón x86 y x86-64 https://triton.quarkslab.com
Verifast C, Java https://people.cs.kuleuven.be/~bart.jacobs/verifast

Versiones anteriores de las herramientas

  1. EXE es una versión anterior de KLEE. El documento EXE se puede encontrar aquí .

Historia

El concepto de ejecución simbólica se introdujo académicamente con descripciones de: el sistema Select, el sistema EFFIGY, el sistema DISSECT y el sistema de Clarke. Consulte una bibliografía de artículos más técnicos publicados sobre ejecución simbólica.

Ver también

Referencias

  1. ^ Anand, Saswat; Patrice Godefroid; Nikolai Tillmann (2008). "Ejecución simbólica composicional impulsada por la demanda". Herramientas y algoritmos para la construcción y análisis de sistemas . Apuntes de conferencias en Ciencias de la Computación. 4963 . págs. 367–381. doi : 10.1007 / 978-3-540-78800-3_28 . ISBN 978-3-540-78799-0.
  2. ^ Ma, Kin-Keng; Khoo Yit Phang; Jeffrey S. Foster; Michael Hicks (2011). "Ejecución simbólica dirigida" . Actas de la 18ª Conferencia Internacional sobre Análisis de Estadísticas . págs. 95-111. ISBN 9783642237010. Consultado el 3 de abril de 2013 .
  3. ^ Staats, Matt; Corina Pasareanu (2010). "Ejecución simbólica en paralelo para la generación de pruebas estructurales". Actas del XIX Simposio Internacional sobre Pruebas y Análisis de Software . págs. 183-194. doi : 10.1145 / 1831708.1831732 . ISBN 9781605588230. S2CID  9898522 .
  4. ^ Kuznetsov, Volodymyr; Kinder, Johannes; Bucur, Stefan; Candea, George (1 de enero de 2012). "Fusión de Estado Eficiente en Ejecución Simbólica". Actas de la 33ª Conferencia ACM SIGPLAN sobre diseño e implementación de lenguajes de programación . Nueva York, NY, EE.UU .: ACM. págs. 193-204. CiteSeerX  10.1.1.348.823 . doi : 10.1145 / 2254064.2254088 . ISBN 978-1-4503-1205-9. S2CID  135107 .
  5. ^ a b DeMillo, Rich; Offutt, Jeff (1 de septiembre de 1991). "Generación de datos de prueba automática basada en restricciones". Transacciones IEEE sobre ingeniería de software . 17 (9): 900–910. doi : 10.1109 / 32.92910 .
  6. ^ Cadar, Cristian; Dunbar, Daniel; Engler, Dawson (1 de enero de 2008). "KLEE: Generación automática y no asistida de pruebas de alta cobertura para programas de sistemas complejos" . Actas de la 8ª Conferencia USENIX sobre Diseño e Implementación de Sistemas Operativos . OSDI'08: 209–224.
  7. ^ Turpie, Jonathan; Reisner, Elnatan; Foster, Jeffrey; Hicks, Michael. "MultiOtter: Ejecución simbólica multiproceso" (PDF) .
  8. ^ Chipounov, Vitaly; Kuznetsov, Volodymyr; Candea, George (1 de febrero de 2012). "La Plataforma S2E: Diseño, Implementación y Aplicaciones". ACM Trans. Computación. Syst . 30 (1): 2: 1–2: 49. doi : 10.1145 / 2110356.2110358 . ISSN  0734-2071 . S2CID  16905399 .
  9. ^ Sharma, Asankhaya (2014). "Explotación de comportamientos indefinidos para una ejecución simbólica eficiente". ICSE Companion 2014: Actas complementarias de la 36ª Conferencia Internacional sobre Ingeniería de Software . págs. 727–729. doi : 10.1145 / 2591062.2594450 . ISBN 9781450327688. S2CID  10092664 .
  10. ^ Cadar, Cristian; Ganesh, Vijay; Pawlowski, Peter M .; Dill, David L .; Engler, Dawson R. (2008). "EXE: Generación automática de entradas de muerte". ACM Trans. Inf. Syst. Asegurar . 12 : 10: 1–10: 38. doi : 10.1145 / 1455518.1455522 . S2CID  10905673 .
  11. ^ Robert S. Boyer y Bernard Elspas y Karl N. Levitt SELECT: un sistema formal para probar y depurar programas mediante ejecución simbólica, Actas de la Conferencia internacional sobre software confiable, 1975, páginas 234--245, Los Ángeles, California
  12. ^ James C. King, Ejecución simbólica y prueba de programas, Comunicaciones del ACM, volumen 19, número 7, 1976, 385-394
  13. ^ William E. Howden, Experimentos con un sistema de evaluación simbólico, Actas, Conferencia Nacional de Computación, 1976.
  14. ^ Lori A. Clarke, A program testing system, ACM 76: Proceedings of the Annual Conference, 1976, páginas 488-491, Houston, Texas, Estados Unidos

enlaces externos