PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so many Bugs?

44 %
56 %
Information about PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write...

Published on October 2, 2016

Author: rwessling

Source: slideshare.net

1. Static Analysis of PHP Code How the Heck did I write so many Bugs? PHPCon Poland, September 2016 By Rouven Weßling ( ) Ecosystem Developer / Developer Evangelist, Contentful @RouvenWessling photo credit: byWarsaw Kamil Porembiński (license)

2. A content management developer platform with an API at its core.

3. What is Static Analysis?

4. Analysing software without executing it.

5. Dynamic Analysis xdebug xhprof PHP Analyzer PHP Vulnerability Hunter Assertions

6. Why use Static Analysis?

7. Spend less time on unit tests...

8. ...and code review

9. class ClientTest extends PHPUnit_Framework_TestCase { public function testGetSynchronizationManager() { $client = new Client('b4c0n73n7fu1', 'cfexampleapi'); $this->assertInstanceOf(Manager::class, $client->getSynchronizationManager()); } }

10. Easy to integrate in Continuous Integration

11. Find issues that can not be found through unit tests

12. PHP 7 Abstract Syntax Tree Scalar Types Strict Types

13. PHP is dynamic Reflection Variable variables Referencing classes/functions/properties by string

14. The more static your code is, the easier it's to reason about.

15. Some tools

16. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter RIPS Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

17. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter RIPS Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

18. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter RIPS Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

19. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter RIPS Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

20. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter RIPS Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

21. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

22. phpmd phan phpcs phpunit phploc phpcpd phpsa php7c Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

23. phpmd phan phpcs phpunit phploc phpcpd phpsa PHP Coupling Detector Mondrian PHP Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PH Semantic Versioning Checker PHP Inspection PHP lint PHP Depend PhpMetrics PHPCheckstyle PHP Reaper PHP vuln hunter Parse SonarQube Side Channel Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHP semver checker

24. PHP lint php -l

25. Compiles PHP script with the actual PHP compiler It's already installed on your computer Can be used to test compatibility with multiple PHP versions

26. <?php namespace ContentfulLog use PsrHttpMessageRequestInterface; use PsrHttpMessageResponseInterface; class NullLogger implements LoggerInterface { public function getTimer() { return new NullTimer; } public function log($api, RequestInterface $request, StandardTimer $timer, Respons { } }

27. PHP 7.0.3 | 10 parallel jobs .................................X...... 40/40 (100 %) Checked 40 files in 0.5 seconds Syntax error found in 1 file ------------------------------------------------------------ Parse error: src/Log/NullLogger.php:9 7| namespace ContentfulLog 8| > 9| use PsrHttpMessageRequestInterface; 10| use PsrHttpMessageResponseInterface; 11| Unexpected 'use' (T_USE), expecting '{'

28. Make your life easier Use PHP-Parallel-Lint

29. phploc

30. Gather stats about your projects Get an idea of the complexity See long term trends

31. phploc 3.0.1 by Sebastian Bergmann. Directories 6 Files 40 Size Lines of Code (LOC) 5683 Comment Lines of Code (CLOC) 2562 (45.08%) Non-Comment Lines of Code (NCLOC) 3121 (54.92%) Logical Lines of Code (LLOC) 951 (16.73%) Classes 868 (91.27%) Average Class Length 21 Minimum Class Length 0 Maximum Class Length 190 Average Method Length 2 Minimum Method Length 0 Maximum Method Length 25 Functions 0 (0.00%) Average Function Length 0 Not in classes or functions 83 (8.73%)

32. Cyclomatic Complexity Average Complexity per LLOC 0.28 Average Complexity per Class 7.65 Minimum Class Complexity 1.00 Maximum Class Complexity 62.00 Average Complexity per Method 1.82 Minimum Method Complexity 1.00 Maximum Method Complexity 11.00

33. If you're getting serious about Cyclomatic Complexity, use phpmd.

34. Dependencies Global Accesses 0 Global Constants 0 (0.00%) Global Variables 0 (0.00%) Super-Global Variables 0 (0.00%) Attribute Accesses 536 Non-Static 535 (99.81%) Static 1 (0.19%) Method Calls 319 Non-Static 308 (96.55%) Static 11 (3.45%)

35. Structure Namespaces 7 Interfaces 3 Traits 0 Classes 37 Abstract Classes 3 (8.11%) Concrete Classes 34 (91.89%) Methods 272 Scope Non-Static Methods 272 (100.00%) Static Methods 0 (0.00%) Visibility Public Methods 221 (81.25%) Non-Public Methods 51 (18.75%) Functions 6 Named Functions 0 (0.00%) Anonymous Functions 6 (100.00%) Constants 2 Global Constants 0 (0.00%) Class Constants 2 (100.00%)

36. Deptrac

37. Software has layers There should be rules about those layers Rules are easily broken

38. 1. Define the layers of your architecture 2. Define what layers another layer can access 3. Profit!!!

39. layers: - name: Controller collectors: - type: className regex: .*Controller.* - name: Entity collectors: - type: className regex: AstaRwthVorkursticketBundleEntity.*

40. ruleset: Controller: - Service - Entity - Form Service: - Repository Command: - Entity Entity: - Validator

41. How it works Parses all files in your code Stores which classes access which others classes Checks the graph for rule violations

42. deptrac is alpha, not production ready. please help us and report feedback / bugs. Start to create an AstMap for 24 Files. ........................ AstMap created. start emitting dependencies "InheritanceDependencyEmitter" start emitting dependencies "BasicDependencyEmitter" end emitting dependencies start flatten dependencies end flatten dependencies collecting violations. formatting dependencies. [...]ServicesPdfOrder::5 must not depend on [...]EntityVorkursticket (Service on Enti [...]ServicesPdfOrder::23 must not depend on [...]EntityVorkursticket (Service on Ent Found 2 Violations

43. phan

44. Type safety for PHP Checks docblocks Signature mismatches Unused code

45. How it works Makes 2 passes over the codebase 1. Build a list of all classes, functions, methods, etc. 2. Go trough each function and follow the type of each variable

46. /** * @param Locale|string|null $locale * * @return string */ public function getDescription($locale = null) { $localeCode = $this->getLocaleFromInput($locale); // This checks happens after the call to getLocaleFromInput to make sure // the Exception for invalid locales is still thrown. if ($this->description === null) { return null; } return $this->description->$localeCode; } src/Delivery/Asset.php:74 PhanTypeMismatchReturn Returning type null but getDescription() is declared to return string

47. class ContentType { /** * The fields, keyed by ID. * * @var object */ private $fields = []; } src/Delivery/ContentType.php:34 PhanTypeMismatchProperty Assigning array to property but contentfuldeliverycontenttype::fields is object

48. public function __call($name, $arguments) { // Lots of code here if ($result instanceof Link) { return $client->resolveLink($result); } return array_map(function ($value) use ($client) { if ($value instanceof Link) { return $client->resolveLink($value); } return $value; }, $result); } src/Delivery/DynamicEntry.php:126 PhanTypeMismatchArgumentInternal Argument 2 (input1) is contentfuldeliverylink but array_map() takes array Not a bug

49. Don't trust blindly

50. Bad news? Requires php-ast Not easy to deal with library code Noisy - not easily integrated in CI.

51. The future

52. phan is using brute force for type checking Roughly as good as the compiler for a statically typed language Works, but a Control Flow Graph could give even deeper insight

53. int foo(int length) { int x = 0; for (int i = 0; i < length; i++) x += 1 return length/x; }

54. Bottom line There are dozens of tools - pick what's necessary for you Make them part of your Continuous Integration setup Never trust. Make sure you understand where the error is coming from.

55. Slides available on Slideshare: http://www.slideshare.net/rwessling Please leave feedback on joind.in ( ) or tweet me ( ) https://joind.in/talk/8f19b @RouvenWessling

Add a comment