280 likes | 419 Views
DART: directed automated random testing by Patrice Godefroid Nils Klarlund Koushik Sen. Rodrigo Alves Costa rac2@cin.ufpe.br 22 de Abril de 2008. O Artigo. Directed Automated Random Testing (DART) Apresentado em: PLDI 2005. Objetivo de DART.
E N D
DART: directed automatedrandom testingby Patrice Godefroid Nils Klarlund Koushik Sen Rodrigo Alves Costa rac2@cin.ufpe.br 22 de Abril de 2008
O Artigo • Directed Automated Random Testing (DART) • Apresentado em: PLDI 2005 Rodrigo Costa <rac2@cin.ufpe.br>
Objetivo de DART • Ferramenta para automatizar geração de testes • Gera entradas alternando execução simbólica e aleatória. Rodrigo Costa <rac2@cin.ufpe.br>
Execução simbólica • DIRECIONA o programa em caminhos inexplorados. • Geração de novas entradas de maneira a satisfazer path conditions. a a path condition: a, b b b b Rodrigo Costa <rac2@cin.ufpe.br>
Execução simbólica de test_me($x, $y) int double ( int x ) { return 2 * x; } void test_me ( int x, int y ) { int z = double ( x ); if ( z==y ) { if ( y == x+10 ) abort(); /* ERRO */ } } Rodrigo Costa <rac2@cin.ufpe.br>
Execução simbólica de test_me($x, $y) int double ( int x ) { return 2 * x; } void test_me ( int x, int y ) { int z = double ( x ); if ( z==y ) { if ( y == x+10 ) abort(); /* ERRO */ } } 2 *$x != $y 2 *$x == $y $y != $x + 10 $y == $x + 10 Rodrigo Costa <rac2@cin.ufpe.br>
Execução simbólica de test_me($x, $y) int double ( int x ) { return 2 * x; } void test_me ( int x, int y ) { int z = double ( x ); if ( z==y ) { if ( y == x+10 ) abort(); /* ERRO */ } } 2 *$x != $y 2 *$x == $y $y != $x + 10 $y == $x + 10 path condition: 2 *$x == $y, $y == $x + 10 path condition: 2 *$x == $y, $y != $x + 10 path condition: 2 *$x != $y Rodrigo Costa <rac2@cin.ufpe.br>
Elementos de uma execução simbólica • Componentes de um estado em uma execução simbólica Path condition – quando é que este caminho é tomado? Estado simbólico – pode ser visto como a “memória” de uma execução simbólica. Rodrigo Costa <rac2@cin.ufpe.br>
Problemas para automação de execução simbólica • Pouco escalável • Principal: restrições indecidíveis • Proposta de DART • Combinar execução simbólica com concreta (escolha de entradas aleatórias). Rodrigo Costa <rac2@cin.ufpe.br>
DART… 1. Automatiza a interface do programa a partir do código-fonte. 2. Geração de um test driveraleatoriamente através da interface. 3. Geração dinâmica de testes, simbolicamente, para direcionar a execução de caminhos alternativos. • Juntos: (1) + (2) + (3) = DART Rodrigo Costa <rac2@cin.ufpe.br>
(1) Extração da interface: • parâmetros da função de mais alto nível • variáveis globais • valores de retorno de funções externas (2) Geração de um test driver aleatório: main() { int tmp1 = randomInt(); int tmp2 = randomInt(); test_me ( tmp1 , tmp2 ); } Geração de um programa auto-executável Exemplo int double ( int x ) { return 2 * x; } void test_me ( int x, int y ) { int z = double ( x ); if ( z==y ) { if ( y == x+10 ) abort(); /* ERRO */ } } A probabilidade de alcançar abort(), e encontrar o erro, aleatoriamente, é extremamente baixa! Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } voidtest_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 36, y = 99 Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 36, y = 99, z = 72 z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica Resolva: 2 * x == y Solução: x = 1, y = 2 crie variáveis simbólicas x, y 2 * x != y x = 36, y = 99, z = 72 z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 1, y = 2 Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 1, y = 2, z = 2 z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 1, y = 2, z = 2 2 * x == y z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica Resolva: (2 * x == y) && (y == x +10) Solução: x = 10, y = 20 crie variáveis simbólicas x, y 2 * x == y y != x + 10 x = 1, y = 2, z = 2 z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 10, y = 20 Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 10, y = 20, z = 20 z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica crie variáveis simbólicas x, y x = 10, y = 20, z = 20 2 * x == y z = 2 * x Rodrigo Costa <rac2@cin.ufpe.br>
Passo (3) do DART: Busca direcionada main() { int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2); } int double(int x) { return 2 * x; } void test_me (int x, int y) { int z = double(x); if (z==y) { if (y == x+10) abort(); /* ERRO */ } } Path Condition Execução Concreta Execução Simbólica Erro encontrado crie variáveis simbólicas x, y 2 * x == y x = 10, y = 20, z = 20 z = 2 * x y == x +10 Rodrigo Costa <rac2@cin.ufpe.br>
Resumo do funcionamento de DART • Geração dinâmica de testes para direcionar a execução dos diversos caminhos do código. • Coleta restrições simbólicas em branches. Caminhos não percorridos são armazenados para próximas execuções. • Utiliza provadores de teorema em novos PC para gerar novas entradas. Quando não consegue, chuta valores aleatórios. • A próxima execução é orientada pelas novas entradas para explorar o branch alternativo. • Verifica por meio de instrumentação dinâmica se um determinado branch foi, de fato, explorado. Rodrigo Costa <rac2@cin.ufpe.br>
Resultados • Protocolo de autenticação NS (Needham-Schroeder) • Cerca de 400 linhas de código C, em um P-III 800Mhz rodando Linux. • DART demorou menos de 2 s (664 tentativas) para descobrir uma vulnerabilidade. • Em contrapartida, o VeriSoft (model checker) não achou o problema. • Biblioteca oSIP (Open Source SIP) • 30.000 linhas de código, 600 funções públicas. • DART encontrou erros em 65% das funções em menos de 1.000 tentativas. • A maioria destes erros eram decorrentes da ausência de verificação em ponteiros. Rodrigo Costa <rac2@cin.ufpe.br>
Conclusões • Totalmente automatizado • Extrai a interface, gera os test drivers e os stubs • Tenta explorar todos os caminhos • Busca aleatória • Busca direcionada • Duas limitações principais: • Provadores de teorema. • Possibilidade de nunca terminar (path explosion). • Solução: SMART (DART escalável) • Exemplos de implementação do DART • Bell labs – versão do paper • CUTE (UIUC) • “Execution-generated tests” (Stanford) Rodrigo Costa <rac2@cin.ufpe.br>
Perguntas? Rodrigo Costa <rac2@cin.ufpe.br>
BACKUP Rodrigo Costa <rac2@cin.ufpe.br>
Arquitetura (DART para C) prgm.c CIL (Berkeley) dart (OCaml, C) test_driver.c prgm_instrumented.c Compilador prgm.exe dart.c 3 possíveis saídas: • Erro encontrado • Cobertura completa • Loop infinito… provador de teorema Rodrigo Costa <rac2@cin.ufpe.br>