Php Sat Getting Started
Static analysis for PHP
Analyzing a file
After you have
installed php-sat you can run it by typing:
php-sat -h
If this command does not produce a list of all the options that are available for php-sat you should check your installation.
We will start with a simple file,
foo.php that contains an example of the bug-pattern
C002:
$ cat foo.php
<?php
function foo($bar){
echo $bar;
}
foo("param1", "param2");
?>
We can feed this to php-sat by using the
-i
option (we also use the
--extended-output
option to show the complete file again):
$ php-sat -i foo.php --extended-output
<?php
function foo($bar){
echo $bar;
}
/**
* PHP-SAT check (Correctness)
* Pattern ID : C002
* Description: Too many parameters in function call
*/
foo("param1", "param2");
?>
The output can also be saved into a file by giving the filename to the
-o
option:
$ ls
foo.php
$ php-sat -i foo.php -o foo.php.php-sat --extended-output
$ ls
foo.php foo.php.php-sat
$ cat foo.php.php-sat
<?php
function foo($bar){
echo $bar;
}
/**
* PHP-SAT check (Correctness)
* Pattern ID : C002
* Description: Too many parameters in function call
*/
foo("param1", "param2");
?>
Analyzing multiple files
But what if we have this
foo-simple.php:
$ cat foo-simple.php
<?php
include 'foo.inc';
foo("param1", "param2");
?>
this
foo-complex.php:
$ cat foo-complex.php
<?php
$postfix = 'inc';
include 'foo.'.$postfix;
foo("param1", "param2");
?>
and this
foo.inc:
$ cat foo.inc
<?php
function foo($bar){
echo $bar;
}
?>
The output of php-sat on
foo-simple.php would then be:
$ php-sat -i foo-simple.php --extended-output
<?php
include 'foo.inc';
foo("param1", "param2");
?>
and on
foo-complex.php:
$ php-sat -i foo-complex.php --extended-output
<?php
$postfix = 'inc';
include 'foo.' . $postfix;
foo("param1", "param2");
?>
which is still correct, php-sat only reports things it finds, so reporting nothing is still correct, but we would want php-sat to include the files that are included. There are two modes in which php-sat can include files,
simple and
complex.
Simple inclusion
Simple inclusion means that php-sat will try to include
every file that is included by a
literal name. Every include/require/include_once/require_once statement that is followed by a literal string will be included if the file can be found. This mode does not respect the *_once-semantics, nor will it take into account concatenated names.
So the _php-simple.php_-problem can be solved by passing the
--simple-inclusion
flag to php-sat.
$ php-sat -i foo-simple.php --simple-inclusion --extended-output
<?php
include 'foo.inc';
/**
* PHP-SAT check (Correctness)
* Pattern ID : C002
* Description: Too many parameters in function call
*/
foo("param1", "param2");
?>
This the same output as before, we could even use the
-o
option is we wanted.
The output for
foo-complex.php is still not informative:
$ php-sat -i foo-complex.php --simple-inclusion --extended-output
<?php
$postfix = 'inc';
include 'foo.' . $postfix;
foo("param1", "param2");
?>
Complex inclusion
Complex inclusions is not complex for the user, just for php-sat itself. This mode will trigger
constant-propogation which will, as the name implies, propagate constant information through the scripts. This causes the complex mode to use more resources, but enables a larger set of analysis's.
This mode does respect the semantics of the *_once-statements, so files will only be included the first time they are encountered.
The complex mode can be seen as an extension to the simple mode, every file that is included in the simple mode will also be included by the complex mode.
So the output for
foo-simple.php with the
--complex-inclusion
flag will be:
$ php-sat -i foo-simple.php --complex-inclusion --extended-output
<?php
include 'foo.inc';
/**
* PHP-SAT check (Correctness)
* Pattern ID : C002
* Description: Too many parameters in function call
*/
foo("param1", "param2");
?>
and for
foo-complex.php:
$ php-sat -i foo-complex.php --complex-inclusion --extended-output
<?php
$postfix = 'inc';
include 'foo.' . $postfix;
/**
* PHP-SAT check (Correctness)
* Pattern ID : C002
* Description: Too many parameters in function call
*/
foo("param1", "param2");
?>
Printing included files
In real world situation the included files could also contain bug-patterns. These patterns can either be static, always available in the source file, or dynamic, available under certain inclusion-conditions. It is useful to examine the included files after they are included to check for these patterns.
The default behavior for included files is that they are discarded from the memory after the analysis. This behavior can be altered by passing the
--print-included-files
flag. This flag will print
all included files to the same location as the original files, giving them a =php-sat=-postfix.
Here is a little example with simple inclusion. We have the same files as before:
$ ls
foo-simple.php foo-complex.php foo.php foo.inc
When we use php-sat with a target we get one extra file with a result:
$ php-sat -i foo-simple.php -o foo-simple.php.php-sat --simple-inclusion --extended-output
$ ls
foo-simple.php foo-complex.php foo.php foo.inc foo-simple.php.php-sat
Passing
--print-included-files
will give yet another extra file with a result:
$ php-sat -i foo-simple.php -o foo-simple.php.php-sat --simple-inclusion --print-included-files --extended-output
$ ls
foo-simple.php foo-complex.php foo.php foo.inc foo-simple.php.php-sat foo.inc.php-sat
Interpreting the output
Please take a look at the
bug-patterns section to find out how the results should be interpreted.