php static code review
DESCRIPTION
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.TRANSCRIPT
![Page 1: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/1.jpg)
PHP Static Code Review
München, Deutschland, October 27th
![Page 2: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/2.jpg)
Definition
• A kind of code analysis where the code is reviewed without running it.
• Just like we would do ourselves!
• Where can it help
![Page 3: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/3.jpg)
Who is speaking?
• Damien Seguy
• CTO at exakat
• Phather of the plush toy elePHPant
• Working on automated code audit
![Page 4: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/4.jpg)
![Page 5: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/5.jpg)
PHP tokenizer
<?php function x($a) { return $a;}x(1, 2);?>
[0] => Array ( [0] => 372 [1] => <?php
[2] => 1 )
[1] => Array ( [0] => 334 [1] => function [2] => 2 )
[2] => Array ( [0] => 375 [1] => [2] => 2 )
[3] => Array ( [0] => 307 [1] => x [2] => 2 )
function token
whitespace token
T_STRING
Total : 30 tokens
![Page 6: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/6.jpg)
Internals
Code
Analyze Report
AST
![Page 7: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/7.jpg)
![Page 8: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/8.jpg)
<?php function x($a) { return $a;}x(1, 2);?>
![Page 9: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/9.jpg)
Found• Dead code
• Undefined structures
• Unused structures
• Illogical exp.
• Slow code
• Bad practices
• Unsafe code
• Maintainability
• Bug issue
• Ancient style
• Uninitialized vars
• Taint propagation
![Page 10: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/10.jpg)
<?phpswitch ($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; } }?>
![Page 11: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/11.jpg)
<?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); }
?>
![Page 12: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/12.jpg)
protected function openString($end, &$out=null, $nestingOpen, $rejectStrs = null) { $nestingLevel = $count = 0; $content = array(); while ($this->match($patt, $m, false)) { $tok = $m[2]; if ($tok == "@{" && $this->interpolation($inter)) { $content[] = $inter; continue; } if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) { $ount = null; break; } $content[] = $tok; $count += strlen($tok); } $this->eatWhiteDefault = $oldWhite; if (count($content) == 0) return false; $out = array("string", "", $content); return true; }
![Page 13: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/13.jpg)
Spot bugs early
Code Test PreProd Production
Run it at commit Run it as audit
![Page 14: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/14.jpg)
When does it help
• Audit external libraries
• Help port to a new system
• Search for weak code fragments
• Hint at refactoring
![Page 15: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/15.jpg)
Report
• Bugs
• Useless code
• Suggestions
![Page 16: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/16.jpg)
Bugs
<?php
if($content = file_get_contents($file)) { $content = trim($content); $content = substr($content, -2) == ‘>’ ? substr($content, 0, -2) : $content;}?>
![Page 17: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/17.jpg)
Useless code
<?php
// inside a legit class $this->module->xmlRequest;$_G['setting']['debug'];
if (!empty($a) && in_array($tokens, $a)) { false;}
?>
![Page 18: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/18.jpg)
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];?>
![Page 19: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/19.jpg)
Where it doesn’t help
• Unit tests
• Architecture
• Old traditions that won’t change
• Semantic errors
![Page 20: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/20.jpg)
Architecture
• No framework context
• Conception is done before coding
• Of course!
• Static audit will report standards, not norms
![Page 21: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/21.jpg)
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()
![Page 22: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/22.jpg)
Old traditions
<?php defined('WEB_ROOT') || define('WEB_ROOT', dirname(__FILE_));
// also classic usage fopen($pFilename, 'w') or die("can't open file");
?>
![Page 23: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/23.jpg)
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
![Page 24: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/24.jpg)
Available analyzers• PHP code sniffer
• PHP MD
• Scrutinizer-ci
• Fortify
• insight from Sensio
• Exakat
![Page 25: PHP Static Code Review](https://reader034.vdocuments.site/reader034/viewer/2022052601/558fd96b1a28ab7c528b45c0/html5/thumbnails/25.jpg)
http://www.slideshare.net/dseguy