Análisis/Testing de SW por Seguridad

Transcripción

Análisis/Testing de SW por Seguridad
Análisis/Testing de SW
por Seguridad
Facultad Politécnica – UNA
Maestría en TICs – 2015
Énfasis Auditoría y Seguridad de la Información
Seguridad en aplicaciones y base de datos
Cristian Cappo ([email protected])
NIDTEC - Núcleo de Investigación y Desarrollo Tecnológico - FPUNA
Contenido
 Introducción y motivación
 Técnicas de análisis y testing para hallazgo de
vulnerabilidades




Fuzzing (webscarab)
Análisis estático/dinámico
Test de penetración.
Herramientas disponibles para evaluar seguridad del
código
2
Introducción
 El software juega un rol principal en la provisión
de seguridad y el la mayor fuente de problemas
de seguridad
 El SW es el eslabón más débil en la cadena de
seguridad, con la posible excepción del factor
humano
 No hay bala de plata
 La criptografía o las prestaciones especiales de
seguridad no resuelven mágicamente el problema
 Software security ≠ security Software
 “Si piensas que tu problema se resuelve con criptografía, no
entiendes la criptografía y no entiendes tu problema” [Bruce
Schneier https://www.schneier.com/about.html]
3
Introducción
 La seguridad es una propiedad emergente del
sistema completo
 Semejante a la calidad
 Los aspectos de seguridad deben ser parte
integral del diseño, desde el inicio.
 La seguridad es siempre un aspecto secundario
 El aspecto principal es proveer alguna funcionalidad o
servicio, los riesgos asociados es un derivado/aspecto
secundario.
 Trade-off entre seguridad y funcionalidad donde
típicamente la seguridad..pierde.
4
5
Funcionalidad vs Seguridad
 Funcionalidad es acerca de que el software debe
hacer y la seguridad es acerca de que no debe
hacer
 Batallas perdidas?
 Sistemas operativos
 Con grandes y complejos SO, grandes superficies de ataques
 Lenguajes de programación
 Cada vez más fáciles, eficientes, pero con mecanismos
inseguros y propenso a errores
 Navegadores
 Con muchísimos plug-ins para varios formatos
 Etc, Etc
6
Más debilidades del software
 Ejecutándose en una gran y complicada
infraestructura:
 S.O., plataforma, navegadores, librerias, APIs, etc
 Construido con complejos lenguajes
 De programación pero también SQL, HTML, XML,
CSS, etc
 Usando varias herramientas
 Compiladores, IDEs, preprocesadores, etc
7
Mapa conceptual de seguridad
Quieren maximizar
Propietarios
Disponibilidad/Utilidad
Quieren minimizar
imponen
Contramedidas
reducen
Pueden tener
requieren
de
Vulnerabilidades
Atacantes
explotan
Conduce
a
aumentan
Riesgos
a
Amenazas
aumentan
Valores
Quieren abusar
8
Terminología
 Muchos términos similares: desperfecto/falla
(flaw), vulnerabilidad, bug, error, defecto de
código.
 Una falla/debilidad(flaw) de seguridad
 Usualmente en fase de diseño
 Una vulnerabilidad de seguridad
 Explotable por un atacante
 La vulnerabilidad del software es introducida por
 Una falla en el diseño
 Una falla en la implementación (bug, defecto de
código)
9
 Existen dos tipos de fallas de implementación
 Bugs que pueden ser comprendidos mirando el
código y entendiendo que se quiso hacer:
 Errores de tipeo, confusión de nombre de variables, etc
 Errores lógicos
 Problemas de bajo nivel que solo pueden ser
descubiertos si conoce la plataforma subyacente de
ejecución del programa, por ejemplo:
 Buffer overflow, integer overflow (en binarios)
 SQL Injection, XSS, CSRF (en aplicaciones web)
10
Estado de la seguridad en aplicaciones
 Malas noticias
 La gente continua cometiendo los mismos tipos de
errores
 Buenas noticias
 La gente continua cometiendo los mismos tipos de
errores
11
Combatiendo la “inseguridad” en el software
 Conociendo los errores estándar es crucial para
prevenirlos
 Dependientes del lenguaje de programación, de la
plataforma y del tipo de aplicación
 Muchísima información disponible…
Por ejemplo mirar el libro de 21 errores de seguridad en software por
Howard, LeBlanc y Viega. PDF
 Pero no es suficiente, la seguridad debe ser
tenida en cuenta desde el principio, a través del
ciclo de vida de desarrollo del software (lo que
miramos en clases pasadas).
12
Metodologías para desarrollar software
seguro desde el inicio
 McGraw’s Touchpoint
BSIMM Building Security in – Maturity Model
 Microsoft SDL
 OpenSAMM (Software Assurance Maturity
Model)
Ya miramos en clases pasadas!!
13
Puntos de falla de seguridad - Ejemplo
int balance;
<= debe ser >=
¿Qué pasa si monto
void debito (int monto){
es negativo?
if ( balance <= monto )
balance = balance - monto;
else
printf(“Saldo insuficiente\n”);
}
void credito (int monto) {
balance = balance + monto;
}
¿Qué pasa si monto
es muy grande para
un int?
14
Diferentes tipos de fallas de implementación
¿Qué pasa si monto
es negativo?
1. Posible falta de validación de
entrada del usuario
Puede ser una falla de diseño?
<= debe ser >=
2. Error simple de lógica
¿Qué pasa si monto
es muy grande para un
int?
3. Potencial problema
dependiendo de la plataforma
de ejecución del programa
15
¿Porqué el software tiene vulnerabilidades?
 Programadores son humanos
 Humanos cometen errores
 Programadores no tienen capacitación en
seguridad
 Los lenguajes de programación no están bien
diseñados para seguridad
16
¿Qué podemos hacer?
 Programadores son humanos
 Humanos cometen errores
 Usar herramientas
 Programadores no tienen capacitación en
seguridad
 Aprender sobre clases comunes de errores
 Los lenguajes de programación no están bien
diseñados para seguridad
 Utilizar mejores lenguajes
17
Encontrar bugs
 Atacantes
 Encuentra vulnerabilidades
 Crear un exploit para esa vulnerabilidad
 Utiliza el exploit para comprometer
máquinas/sistemas
 Exploits valen dinero!!
Encontrar
vulnerabilidad
Crear
exploit
Comprometer
US$
18
Mercado de 0day (entre US$ 10K y 100K o más!!)
19
Encontrar bugs
 Defensores
 Encontrar vulnerabilidades y eliminarlas
 Mejorar seguridad en el software
 Más fácil y barato arreglar vulnerabilidades antes del
despliegue del software
 Luego del despliegue: el “parcheo” es caro
 Idealmente probamos que un programa esta libre de
vulnerabilidades
Encontrar
vulnerabilidad
Arreglar
Vulnerabilidad
Arreglo interno
Costo bajo
Parche
Costo alto
20
Técnicas y abordajes para encontrar
vulnerabilidades
Generación
automática
de tests
Fuzzing
Análisis estático
Verificación
de Programas
Ejecución
simbólica
dinámica
Baja cobertura
Pocos falsos positivos
Muchos falsos negativos
Alta cobertura
Pocos falsos negativos
Muchos falsos positivos
21
Testing
 Es un elemento crítico en el ciclo de desarrollo
de software
 Llamado control de calidad del software o SQA
(software quality assurance)
 Metas básicas: validación y verificación
 Validación: construimos el producto correcto?
 Verificación: cumple “X” con su especificación?
 Donde X puede ser código, modelo, diagrama,
requerimiento, etc.
 En cada estado, necesitamos verificar que lo que producimos
representa exactamente su especificación
22
Terminología en testing
 Un error es una falta hecha por un ingeniero
 Debido a una mala interpretación de un requerimiento o
especificación de diseño
 Un falla/bug es una manifestación del error en el
código
 Un failure es una salida/comportamiento
incorrecto causado por la ejecución del bug
 Puede ocurrir inmediatamente o mucho despues de la
ejecución
 El testing intenta hacer emerger los “failures” en el
software
¿Si el sistema pasa todos los tests, esta libre de todos los bugs?
23
NOP
 Bugs puedes estar escondidos en porciones de
código que son ejecutados raramente
 Testing solo prueba la existencia de bugs no su
ausencia. NO todos los bugs ocasionan “failures”.
 Sin embargo, si hacemos un buen trabajo en
crear un conjunto de pruebas que
 Cubre todas las capacidades funcionales del sistema
 Y cubre todo el código usando una métrica como el
de cobertura de branch
 Entonces, incrementa la confianza acerca de la
calidad del sistema desarrollado.
24
Todos los posibles estados/comportamientos del sistema
25
Buscando bugs
26
La literatura indica dividir el espacio en comportamientos
similares y tener muestras de cada partición
27
Testing – tipos (Ingeniería de SW)
 Unitarios
 Por módulo, función. Cubre aspecto de bajo nivel.
 Integración
 Chequea la interacción entre módulos
 Sistema
 Prueba el sistema completo de forma a verificar que
todas las funcionalidades han sido implementadas
 Aceptación
 Realizado por el usuario para probar el sistema
entregado.
28
Tipos de test al código
 Caja negra (black box)
 No se tiene el fuente del sistema.
 Prueba que el sistema se comporta según su
especificación
 Caja gris (grey box)
 Se tiene información de la arquitectura del sistema
 Caja blanca (white box)
 Se tiene acceso al código fuente, podemos estar
seguros de cubrir todos los aspectos del código:
sentencias, branches, paths, etc.
29
Black box testing
30
White box
 Miramos
 Cobertura de código
 Cobertura de sentencias (probar que todas las sentencias se
hayan ejecutado)
 Cobertura de Branch (probar cada arista del grafo de control
de flujo del programa que haya ejecutado una vez)
 Cobertura de condición (probar que todas las combinaciones
condicionales se hayan cubierto)
 Cobertura de camino(probar todos los caminos del grafo de
control de flujo según ciertas heurísticas).
 Manejo de errores
 Verificamos si coincide con la documentación
 Manejo apropiado de recursos
31
Ejemplo del CFG (Control Flow Graph)
32
Coberturas
Sentencias
Branch
Condiciones
Paths
33
Testing en seguridad
 Testing por funcionalidad:
 Pruebo por inputs usuales o valores límites
 Testing por seguridad:
 Prueba por entradas totalmente anómalas y con
intenciones maliciosas generalmente.
 Una técnica es la de fuzzing.
34
Fuzzing
35
Test fuzzing de black-box
 Dado un programa, simplemente alimentarlo
con entradas randómicas y verificar si falla.
 Ventaja: muy fácil
 Desventaja: ineficiente
 Las entradas requieren a veces estructura, puede que
las generadas aleatoriamente estén malformadas
 La probabilidad de encontrar una entrada que haga
mal funcionar el software es bastante baja.
36
 Regresión vs. Fuzzing
 Regresión:
 Ejecutar el programa con muchos inputs normales, buscando
por la entrada mala.
 Previene que usuarios normales encuentren errores
 Fuzzing:
 Ejecutar el programa con muchos inputs anormales,
buscando por la entrada mala.
 Previene que los atacantes encuentren errores explotables
37
Fuzzing: mejora I
 Fuzzing basado en mutación
 Tomar una entrada normal y perturbarla
randómicamente
 No asume conocimiento sobre la estructura de la
entrada
 Anomalías pueden ser completamente aleatorias o
seguir alguna heurística (ej. remover NUL, desplazar
caracteres hacia adelante, etc)
 Ejemplo: zzuf (mirar demo)
38
Fuzzing: mejora II
 Fuzzing basado en generación
 Son generados en base a alguna descripción de
formato: RFC, documentación, etc.
 Anomalías son agregadas en lugares posibles de la
entrada
 Conocimiento el protocolo debe dar un mejor
resultado que el fuzzing aleatorio
39
Herramientas fuzzy
 Generación de la entrada
 Usando algún fuzzer
 Veremos como utilizar OWASP ZAP para generar entradas
para nuestro sistema de prueba
 Inyección de la entrada
 Simple (usar el archivo modificado, cambiar el
paquete, etc), modificar el cliente para que invoque
al fuzzer adecuadamente ó usando un framework de
fuzzing
 Detección de bug
 Ver si el programa falla, correr bajo un detector de
falla de memoria dinámica (ejemplo valgrind)
40
Ejercicio #1
 Indique cuantos tests (y dé un ejemplo) serán
necesarios para el siguiente código a fin de
realizar: (Haga antes CFG)
 Cobertura de sentencias
 Cobertura de branch
 Cobertura de caminos (cuantos caminos existen?)
if (
a
if (
b
a
=
b
=
> 2 )
2;
> 2 )
2;
41
Ejercicio #2
Considere el siguiente código:
void mySafeCpy(char *dst, char* src){
if(dst && src)
strcpy(dst, src);
}
 Una cobertura de sentencias ¿garantiza
encontrar el bug?
 Una cobertura de branch ¿garantiza encontrar el
bug?
 Haga el CFG antes.
42
Análisis estático
 Los métodos tradicionales para encontrar
errores
 Testing
 Inspección o revisión de código
 Algunos errores son difíciles de hallar con estos
métodos, ya que
 Surgen en circunstancias inusuales/caminos de
ejecución no comunes
 Buffer overflow, input invalidado, excepciones
 Envuelve no-determinismo
 Race-conditions
43
Testing
Input
..
int main(…) {
--}
 Beneficios
Es correcto?
Output
oráculo
 Fallas concretas proveen justificación de los errores y
ayudan a repararlos.
 Problemas
 Caro, dificultoso, difícil de cubrir todos los caminos,
no garantiza encontrar todos los errores.
44
Inspección de código o auditoría del código
..
int main(…) {
--}
..
void f1(…) {
--}
..
int f2(…) {
--}
 Beneficios
 El humano puede generalizar con una simple revisión
 Problemas
 Caro (con respecto al tiempo de una computadora),
trabajoso y no hay garantías de cobertura.
45
Análisis estático
 Analiza el programa sin ejecutarlo
(la inspección de
código se le deja a la computadora)
 Beneficios
 Es de alta cobertura
 Problemas
 Puede analizar propiedades limitadas
 Puede errar/olvidar algunos problemas=>falsas
alarmas
 Puede consumir mucho tiempo de ejecución
46
Análisis estático – usos típicos
 Para optimizar el código





Detectar variables no utilizadas
Eliminar código muerto
Detectar expresiones usadas frecuentemente
Descubrir métodos sin efectos colaterales
Desreferencias de objetos válida (evitar el chequeo
de null)
 Verificación
 De contratos explícitos o implícitos
 Propiedades funcionales
 Errores “mecanicos”
47
Análisis estático – usos típicos
 Para entender programas




Inferir el tipo de una función
Cálculo pre/pos, invariantes
Requerimientos de memoria
Reingeniería
 Mejorar la calidad/legibilidad de código
 Puede chequear si los programas adhieren a patrones
de buenas prácticas.
48
Impacto del análisis estático
 Aunque analiza propiedades limitadas, las que analiza
son muy útiles
 Elimina categoría de errores
 Los desarrolladores pueden concentrarse en razonamientos más
profundos
 Ayuda/auxilia a mejores prácticas de desarrollo
 Desarrolla modelos de programación que evita errores en
primer lugar
 Ayuda a los programadores a pensar acerca y como manifestar
sus asunciones
 Por ejemplo con notaciones especiales para mejorar la precisión de la
herramienta
 Adopción comercial en aumento
49
¿Qué puede hacer el Análisis estático?
 El problema de la Parada
 Puedo escribir un analizador que pueda probar, para
cualquier programa P y una entrada para él, que P
terminará?
 Llamado Problema de la Parada (Halting Problem)
..
int main(…) {
--}
¿Siempre
termina?
P
oráculo
 Desafortunadamente este problema es indecidible,
es decir, es imposible escribir tal analizador.
 Demostrado por Alan Turing en los 30’s Wiki
50
 Aunque no podemos determinar la terminación
del programa podemos determinar algunas
propiedades que son interesantes a nivel de
seguridad
 Por ejempo a[i] -> está en los límites?
 Podemos eliminar muchos problemas de memoria
 Pero esta propiedad puede también
transformarse en el problema de la Parada y
volverse indecidible.
 Esto es, un verificador perfecto de límites de un
arreglo puede resolver el Problema de la Parada, el
cual es imposible!!
51
 Entonces, ¿es el analizador estático posible?
 El perfecto NO pero uno útil SI a pesar de
 No terminación / puede fallar en terminarse a si mismo
 Falsas alarmas. Dice que hay error y no lo hay
 Errores no reportados (olvidados) que es diferente a “NO
existen errores”
 La NO terminación es difícil de analizar así que las
herramientas tienden a exhibir falsas alarmas y errores
no capturados
 Se encuentran entre la solvencia o correctitud (soundness) y la
completitud (completeness)
52
Cosas verdaderas
Cosas que
digo
Un análisis trivial
correcto: no digo nada
completeness
soundness
 Soundness (propiedad): si el AS (analizar estático) dice que X es
verdadero, entonces X es verdadero)
 Completeness: si X es verdadero, entonces el AS dice que X es
verdadero
Cosas que digo
Cosas
verdaderas
Un análisis trivial
completo: digo todo!!
53
 Ambos dicen exactamente el conjunto de cosas
verdaderas.
 Pero por el problema de la indecibilidad no tenemos
ambos casos al mismo tiempo así que sacrificamos uno
de ellos
 Soundness: si se dice que el programa no tiene error
realmente es así. Alarmas no implica errores
 Completeness: si se dice que el programa es erróneo,
realmente lo es. Silencio no implica que NO hayan errores
 Muchos análisis interesantes no son ni soundness ni
completeness (o ambos). Tienden hacia una u otra
propiedad
54
 Debido que el análisis estático perfecto es imposible la
idea es construir herramientas útiles.
 Diseño del AS – tradeoff
 Precisión: modelar cuidadosamente el comportamiento de un
programa para minimizar las falsas alarmas
 Escalabilidad: analizar exitosamente grandes programas.
 Comprensibilidad: entendibles por los humanos
 Si existe un estilo de código (Coding style) el análisis
puede mejorarse.
 Ayuda a la precisión para buenos programas
 Evitar código enmarañado en nombre de la seguridad
 Falsas alarmas son vistas positivamente: reduce la complejidad
vía la mejora hecha por el programador
55
Análisis de flujo (Flow analysis)
 Es un tipo particular de AS. Rastrea como los datos
pueden fluir entre diferentes posiciones de memoria en
un programa.
 Es interesante en términos de seguridad porque nos ayudan a
encontrar errores que son causa de muchos ataques que se
basan en confianza de entradas no validadas.
 La entrada de un usuario es siempre “contaminada”(tainted)
 Varios datos usados se esperan que sean no contaminadas
(untainted)
 Ejemplos:
 Fuente de strcpy ( <= tamaño del buffer)
 Cadena de Formato de printf (no tiene especificadores de formato)
 Campo de formulario para contruir SQL (no contiene comandos
SQL)
56
Formato de cadenas
char * name = fgets(.., network_fd);
..
printf(name); //..upss!!
Atacante coloca en name = “%s%s%s”
Atacante coloca en name = “..%n” para escribir en memoria (ataque
de inyección)
57
El problema en los tipos
 Especificar nuestro requerimiento como un
qualificador de tipo
int printf( untainted char * fmt,..)
tainted char * name = fgets(…);
tainted: posiblemente controlado por el adversario
untainted: no debe ser controlado por el adversario
tainted char * name = fgets(.., network_fd);
printf(name); // FAIL tainted  untainted
58
 Problema:
 Para todos los posibles inputs, probar que datos
contaminados (tainted) nunca serán usados donde
son esperados datos no contaminados (untainted)
 untainted
 tainted
: trusted sink
: untrusted source
 Una solución requiere inferir el flujo en el programa
 Que fuentes (source) puedan alcanzar los usos (sink)
 Si cualquier flujo es ilegal. Esto es, si una fuente (source)
confiable puede fluir a un uso no confiable.
59
void f( tainted int);
untainted int a = ;
f(a);
void g( untainted int);
tainted int b = ;
g(b);
F acepta
datos tainted o untainted
g acepta
solo datos untainted
untainted <= tainted
tainted <= untainted
Es LEGAL
Es ILEGAL
Existe una relación de orden (lattice) tainted < untainted
Se permite el flujo cuando se respeta el orden
60
Abordaje
 Pensar en el AS como una clase de inferencia de tipo
 Si no existe un qualificador, debemos inferirlo
 Pasos
 Crear un nombre por cada qualificador que falta (,)
 Por cada sentencia en el programa, generar restricciones ( de la
forma q1<= q2) en posibles soluciones
 Sentencia x=y genera la restricción qy <= qx donde qy es el
qualificador de y y qx es el qualificador de x.
 Resolver las restricciones para producir soluciones para ,
 Una solución es una sustitución de qualificadores (como
tainted/untainted) para los nombres (como ,) tal que todas las
restricciones sean FLUJOS LEGALES
 Si no hay solución, nosotros tenemos (o podemos) un FLUJO
ILEGAL.
61
Ejemplo completo
int printf(untainted char * fmt,..);
tainted char * fgets(..);
1er paso: asignar nombres
 char * name = fgets(.., network_id);
 char * x = name; 3er paso: resolver las restricciones
printf(x);
2do paso: restricciones
tainted <= 
 <= 
 <= untainted
tainted <=  <=  <= untainted
1ra. Restr. requiere  = tainted
2da. Restr. requiere  = tainted
3ra. Restr. requiere tainted <= untainted
Por tanto tenemos un flujo ILEGAL y no
Existe una solución para  y 
62
 Variantes del análisis anterior(no veremos en
detalle)
 Insensibles al flujo (básicamente lo que vimos)
 Sensibles al flujo
 Agregamos precisión de flujos condicionales
 Sensible al camino(path)
 Más precisión pero requiere más recursos
 Sensible al contexto
 Llamadas entre funciones
63
Otros tipos de análisis estático
 Análisis de punteros (“points-to” analysis)
 Determina cuando los punteros apuntan a la misma
región (aliases)
 Data flow analysis
 1970. Sensible al flujo. Flujo de datos en variables
del programas. Usado para optimización en
compiladores. Análisis de vivacidad de variables
 Abstract interpretation
 1970. Permite ejecutar un programa en base a
abstracciones. Las abstracciones descartan
información (detalles en diapositivas finales)
64
Análisis Estático en la práctica
 Comerciales
/ Fortify
 OpenSource
65
Detalles de AS OpenSource
 Splint (Lenguaje C) (www.splint.org)
 Detecta vulnerabilidades y errores comunes de
seguridad (por ejemplo posible buffer overflow)
 Permite annotations (ejemplo
/*@requires maxSet(s1) >= ( n - 1 ); @*/
 FingBugs (para Java) (findbugs.sourceforge.net)




Universidad de Maryland
Identifica patrones comunes de errores
Usado por Google hasta hoy día
Detecta vulnerabilidades de seguridad
66
Próxima clase
 Análisis estático por interpretación abstracta
(abstract interpretation)
 Ejecución simbólica
 Test de penetración
 Seguridad en base de datos
67
Bibliografía y referencias
 McGraw G. Software Security: Building Security
in. Addison-Wesley. 2005.
 Brian Chess/Jacob West.Secure Programming
with static analysis. Addison-Wesley. 2007.
 Cursos/Materiales sobre seguridad en:
 http://www.cs.ru.nl/E.Poll/ss/
 http://www.cs.berkeley.edu/~dawnsong/teaching/f12cs161/syllabus.html
 http://realsearchgroup.org/SEMaterials/tutorials/index.php
 https://wiki.engr.illinois.edu/display/ece422sp13/Home
 http://www.utdallas.edu/~muratk/courses/dbsec09s.htm
 Software Security (University of Maryland) - Coursera
68
¡Gracias!
¿Preguntas?
69
Análisis estático
 Recordando: es la revisión sistemática de una
abstracción del espacio de estados del programa
 Sistemática
 Examinamos todos los caminos posibles dentro de
cada función
 La exploración es exhaustiva
 Abstracción
 Solo se mantiene información relevante a la
propiedad a inferir
 Por ejemplo: Signo de variables
70
AS - Abstracción
 Abstracción
 Solo se mantiene información relevante a la
propiedad a inferir
 Por ejemplo: Signo de variables
 Enfocarse en la propiedad a analizar
 Qué aspecto me interesa?




Control: secuencia de eventos, concurrencia, etc
Datos: división por cero, consumo de memoria
Seguridad
Funcionalidad
71
AS – Ejemplo de abstracciones
 Me interesa saber si hay una
posible desreferencia a null
 : Var ->{null,noNull,quizasNull}
 Me interesa evitar división
por cero
 :Var -> {indef,Z, NZ, QZ}
 Puedo liberar la memoria
usada por el iterador al
salir del método
 : grafo de points-to
 Ver alcanzibilidad
72
AS - Abstracción
 Abstracción requiere aproximación ya que no
maneja el estado completo
 No tenemos información real
 Ejemplo: naturales positivos
 3–3=0
 Abs(3) = NZ
 ¿Cuánto es NZ-NZ?
 Es Z o NZ => MZ
73
AS - análisis
 Control flow analysis
 If (b) {c = 5;} else { c=6;} inicializa c
 If (b) {c = 5;} else { d=6;} no inicializa
 Data flow analysis
 d = 5; c = d; inicializa c
 c = d; d = 5; no inicializa
 ¿Inicializa c en la siguiente expresión?
 If ( i < 5 ) { c = 5; }
 If ( i < 0 ) || ( (i * i) > 20) {c = 6;}
 Un AS puede reportar: NO sabe, un falso
positivo, un falso negativo.
74
AS – Ejemplo de determinación de
división por cero
 Veremos análisis de dataflow
 Elementos
 Grafo de control de flujo
 Valores abstractos
 Z, NZ, MZ (Zero, No Zero, May be Zero)
 Funciones de transferencia




F(Z+NZ)=NZ
F(Z+Z)=Z
F(Z-Z)=Z
F(NZ-NZ)=MZ
75
76
77
78
79
80
81
Diagrama de uso de un analizador estático
82

Documentos relacionados