Even nowadays, PHP code is mostly manually audited. Expert pore over actual code, in search for bugs or code smells. Actually, it is possible to have PHP do this work itself ! Strengthened with the internal Tokenizer, bolstered by the manual, it is able to scan thousands of lines of code, without getting bored, and bringing pragmatic pieces of wisdom: official manual recommendations, version migration, code pruning and security. In the end, it deliver a global overview of the code, without reading it.
9. Found
• Dead code
• Undefined structures
• Unused structures
• Illogical exp.
• Slow code
• Bad practices
• Unsafe code
• Maintainability
• Bug issue
• Ancient style
• Uninitialized vars
• Taint propagation
10. <?php
switch ($this->consume())
{
case "x09":
case "x0A":
case "x0B":
case "x0B":
case "x0C":
case "x20":
case "x3C":
case "x26":
case false:
break;
case "x23":
switch ($this->consume())
{
case "x78":
case "x58":
$range = '0123456789ABCDEFabcdef';
return $a++;
break;
}
}
?>
11. <?php
class x extends y {
function array_single_quote($array) {
return parent::array_map("single_quote", $array);
}
}
/* Calling each other */
function debug_dump_backtrace($msg='Calling BackTrace',$die=false) {
debug_sysmsg($msg);
error($msg,'note',null,$die,true);
}
/* Defined in another file */
function debug_sysmsg($msg) {
system_message(array(‘title'=>_('Debug'),'body'=>$msg,'type'=>'debug'));
debug_dump_backtrace($msg, true);
}
?>
17. Useless code
<?php
// inside a legit class
$this->module->xmlRequest;
$_G['setting']['debug'];
if (!empty($a) && in_array($tokens, $a)) {
false;
}
?>
18. Suggestions
<?php
// Nested ternary should be turned into if then structures
$operation == 'ENCODE' ? sprintf('%010d', $expiry ? $expiry + time( ) : 0) . substr(md5
($string . $egiskeys), 0, 16) . $string : base64_decode(substr($string, $key_length))
// Multiply by one is useless
SetCache($prefix, $key, $row, 60*60*1);
$xtime *= 1;
// Backward compatible syntax
$bits = split('.', $string);
$y = $bits[0];
// Available syntax with recent PHP versions
$y = split('.', $string)[0];
?>
19. Where it doesn’t help
• Unit tests
• Architecture
• Old traditions that won’t change
• Semantic errors
20. Architecture
• No framework context
• Conception is done before coding
• Of course!
• Static audit will report standards,
not norms
21. Old traditions
<?php
$pna = explode(')(', $pn);
while (list($k, $v) = each($pna)) {
$lst = explode('"', $v);
if (isset($lst[3])) {
$pn[$lst[1]] = $lst[3];
} else {
$pn[$lst[1]] = '';
}
}
?>
10 % of nowadays applications uses this instead of foreach()
22. Old traditions
<?php
defined('WEB_ROOT') || define('WEB_ROOT', dirname(__FILE_));
// also classic usage
fopen($pFilename, 'w') or die("can't open file");
?>
23. Semantic errors
<?php
$babycarriage = new carriage();
$wheel1 = new Racingwheel();
$wheel2 = new Racingwheel();
$wheel3 = new Racingwheel();
$wheel4 = new Rhinoceros();
$babycarriage->installWheels($wheel1,
$wheel2,
$wheel3,
$wheel4);
?>
Undefined classes : Vehicle, Racingwheel, Rhinoceros
24. Available analyzers
• PHP code sniffer
• PHP MD
• Scrutinizer-ci
• Fortify
• insight from Sensio
• Exakat