Bug hunter: Fuzz testing e Reflection

Há alguns dias atrás comecei a escrever um script que pudesse testar todas os métodos e funções das extensões habilitadas no PHP, passando com argumento valores pré-definidos, afim de encontrar falhas. Este tipo de teste, é denominado "Fuzz testing". Veja abaixo a informação contida na Wikipedia:


Fuzz testing or fuzzing is a software testing technique that provides random data ("fuzz") to the inputs of a program. If the program fails (for example, by crashing, or by failing built-in code assertions), the defects can be noted.


The great advantage of fuzz testing is that the test design is extremely simple, and free of preconceptions about system behavior. Fuzz testing was developed at the University of Wisconsin-Madison in 1988/89 by Professor Barton Miller and the students in his graduate Advanced Operating Systems class.
[1]

Pois bem, para realizar tal feito, é necessário saber quantos argumentos a função/método espera, no mínimo, a quantidade de parâmetros obrigatórios.

Para obter tais informações, foi necessário o uso da extensão Reflection, que provê obviamente, Reflexão.

Na wikipedia vemos a seguinte definição:


In computer science, reflection is the process by which a computer program can observe and modify its own structure and behavior. The programming paradigm driven by reflection is called reflective programming.

A qual foi uma bela adição ao PHP, a partir da versão 5, e que na versão 5.3 (ainda alpha) ela não pode ser desabilitada. Enfim, com ela é possível fazer a engenharia-reversa das funções nativas, e as criadas por usuário via código PHP.

A informação dos parâmetros é declarada internamente simplesmente como visto abaixo:

static
ZEND_BEGIN_ARG_INFO_EX(arginfo_strtotime, 0, 0, 1)
	ZEND_ARG_INFO(0, time)
	ZEND_ARG_INFO(0, now)
ZEND_END_ARG_INFO()

O número 1 ali informa a quantidade de argumentos que são obrigatórios, na parte do ZEND_ARG_INFO, o 0 indica que o argumento não é esperado para ser passado por referência, e 'time' e 'now' são os nomes dos parâmetros.

Representando assim, o que é visto no protótipo na documentação:

int strtotime ( string $time [, int $now ] )

Sendo assim, usando Reflection, nós obtemos a quantidade de parâmetros requeridos e o total, tão somente com:

<?php
 
$func = new ReflectionFunction('strtotime');
 
printf("Arg. obrigatórios: %d\nTotal: %d\n", 
	$func->getNumberOfRequiredParameters(),
	$func->getNumberOfParameters());
 
?>

Produzindo:

Arg. obrigatórios: 1
Total: 2

Há muitas outras informações que podem ser obtidas, não somente de funções, mas também de extensões, classes, propriedades, métodos e de um dado objeto.

Para saber mais, consulte a documentação da Reflection, a estrutura ficou bem legal. :)

Tendo a quantidade, eu criei um loop que vai da maior quantidade possível até o número de argumentos obrigatórios, passando para todos os parâmetros um dado valor pré-definido em um array de valores.

O resultado foi como esperado, para esse tipo de teste em um grande projeto. Foi possível encontrar vários bugs (memory overlap, leaks e seg. fault) "imperceptíveis a olho nu", que felizmente já foram reparados. :)

O código desse meu script chamado "bughunter" pode ser visto em:
https://code.launchpad.net/~felipensp/bughunter/trunk

Note que adicionalmente eu coloquei um outro teste destinado a classes, que é para verificar o comportamento de seus handlers, que são definidos internamente para o controle de leitura & escrita de propriedades (array separadamente), a parte de serialização e deserialização, unset, clonagem do objeto, etc.

Um detalhe que pode ser visto logo no começo do código, é que foi preciso definir items a serem pulados no teste pois algumas funções, por exemplo, abortam a execução, ou pelo tamanho do inteiro passado como argumento, toma bastante tempo para ser executada a função, ou coisas do gênero. Foram realmente necessários.

E é isso, viva aos testes automatizados. :)
Novas idéias de testes são bem vindas, o script continuará a ser atualizado na url supracitada.

[1] - http://en.wikipedia.org/wiki/Fuzz_testing

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options