dart: directed automated random testing by patrice godefroid nils klarlund koushik sen

28
DART: directed automated random testing by Patrice Godefroid Nils Klarlund Koushik Sen Rodrigo Alves Costa [email protected] 22 de Abril de 2008

Upload: colton-wise

Post on 04-Jan-2016

57 views

Category:

Documents


0 download

DESCRIPTION

DART: directed automated random testing by Patrice Godefroid Nils Klarlund Koushik Sen. Rodrigo Alves Costa [email protected] 22 de Abril de 2008. O Artigo. Directed Automated Random Testing (DART) Apresentado em: PLDI 2005. Objetivo de DART. - PowerPoint PPT Presentation

TRANSCRIPT

DART: directed automatedrandom testing

by Patrice GodefroidNils KlarlundKoushik Sen

Rodrigo Alves Costa [email protected] de Abril de 2008

2 Rodrigo Costa <[email protected]>

O Artigo

Directed Automated Random Testing (DART) Apresentado em: PLDI 2005

3 Rodrigo Costa <[email protected]>

Objetivo de DART

Ferramenta para automatizar geração de testes

– Gera entradas alternando execução simbólica e aleatória.

4 Rodrigo Costa <[email protected]>

Execução simbólica

DIRECIONA o programa em caminhos inexplorados.

– Geração de novas entradas de maneira a satisfazer path conditions.

a a

b bb

path condition: a, b

5 Rodrigo Costa <[email protected]>

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 */

}

}

6 Rodrigo Costa <[email protected]>

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

7 Rodrigo Costa <[email protected]>

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 */

}

}

path condition: 2 *$x == $y, $y == $x + 10

path condition: 2 *$x == $y, $y != $x + 10

path condition: 2 *$x != $y

2 *$x != $y 2 *$x == $y

$y != $x + 10 $y == $x + 10

8 Rodrigo Costa <[email protected]>

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.

9 Rodrigo Costa <[email protected]>

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).

10 Rodrigo Costa <[email protected]>

DART…

1. Automatiza a interface do programa a partir do código-fonte.

2. Geração de um test driver aleatoriamente 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

11 Rodrigo Costa <[email protected]>

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 */

}

}

(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

main() {

int tmp1 = randomInt();

int tmp2 = randomInt();

test_me ( tmp1 , tmp2 );

}

(2) Geração de um test driver aleatório:

Geração de um programa auto-executável

A probabilidade de alcançar abort(), e encontrar o erro, aleatoriamente, é extremamente baixa!

12 Rodrigo Costa <[email protected]>

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 */

}

}

Execução Concreta

Execução Simbólica

Path Condition

x = 36, y = 99x = 36, y = 99 crie variáveis crie variáveis simbólicas x, ysimbólicas x, y

13 Rodrigo Costa <[email protected]>

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

crie variáveis crie variáveis simbólicas x, y simbólicas x, y x = 36, y = 99,x = 36, y = 99,

z = 72z = 72 z = 2 * xz = 2 * x

Execução Concreta

Execução Simbólica

14 Rodrigo Costa <[email protected]>

Passo (3) do DART: Busca direcionada

Path Condition

x = 36, y = 99,x = 36, y = 99,z = 72z = 72 z = 2 * xz = 2 * x

2 * x != y2 * x != y

Resolva: 2 * x == yResolva: 2 * x == y

Solução: x = 1, y = 2Solução: x = 1, y = 2

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 */

}

}

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

15 Rodrigo Costa <[email protected]>

Passo (3) do DART: Busca direcionada

Path Condition

x = 1, y = 2x = 1, y = 2

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 */

}

}

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

16 Rodrigo Costa <[email protected]>

Passo (3) do DART: Busca direcionada

Path Condition

x = 1, y = 2, z = 2x = 1, y = 2, z = 2z = 2 * xz = 2 * x

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 */

}

}

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

17 Rodrigo Costa <[email protected]>

Passo (3) do DART: Busca direcionada

Path Condition

x = 1, y = 2, z = 2x = 1, y = 2, z = 2z = 2 * xz = 2 * x 2 * x == y2 * x == y

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 */

}

}

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

18 Rodrigo Costa <[email protected]>

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 */

}

}

Passo (3) do DART: Busca direcionada

Path Condition

2 * x == y2 * x == y

x = 1, y = 2, z = 2x = 1, y = 2, z = 2 z = 2 * xz = 2 * x

y != x + 10y != x + 10

Resolva: (2 * x == y) Resolva: (2 * x == y) && && (y == x +10)(y == x +10)

Solução: x = 10, y = 20Solução: x = 10, y = 20

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

19 Rodrigo Costa <[email protected]>

Passo (3) do DART: Busca direcionada

Path Condition

x = 10, y = 20x = 10, y = 20

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 */

}

}

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

20 Rodrigo Costa <[email protected]>

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 */

}

}

Passo (3) do DART: Busca direcionada

Path Condition

x = 10, y = 20, z = 20x = 10, y = 20, z = 20z = 2 * xz = 2 * x

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

21 Rodrigo Costa <[email protected]>

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 */

}

}

Passo (3) do DART: Busca direcionada

Path Condition

x = 10, y = 20, z = 20x = 10, y = 20, z = 20z = 2 * xz = 2 * x 2 * x == y2 * x == y

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

22 Rodrigo Costa <[email protected]>

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 */

}

}

Passo (3) do DART: Busca direcionada

Path Condition

2 * x == y2 * x == y

y == x +10y == x +10z = 2 * xz = 2 * xx = 10, y = 20, z = 20x = 10, y = 20, z = 20

Erro encontrado

crie variáveis crie variáveis simbólicas x, y simbólicas x, y

Execução Concreta

Execução Simbólica

23 Rodrigo Costa <[email protected]>

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.

24 Rodrigo Costa <[email protected]>

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.

25 Rodrigo Costa <[email protected]>

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)

26 Rodrigo Costa <[email protected]>

Perguntas?

27 Rodrigo Costa <[email protected]>

BACKUP

28 Rodrigo Costa <[email protected]>

Arquitetura (DART para C)

prgm.cprgm.c dart

test_driver.c

prgm_instrumented.c

dart.c

provador de teorema

prgm.exeCompilador

CIL (Berkeley)

• Erro encontrado• Cobertura completa• Loop infinito…

3 possíveis saídas:

(OCaml, C)