54
Static Analysis of PHP Code How the Heck did I write so many Bugs? International PHP Conference Berlin, June 2016 By Rouven Weßling ( ) Ecosystem Developer / Developer Evangelist, Contentful @RouvenWessling photo credit: by Achim Fischer Brandenburg Gate Berlin (license)

Static Analysis of PHP Code – IPC Berlin 2016

Embed Size (px)

Citation preview

Page 1: Static Analysis of PHP Code – IPC Berlin 2016

Static Analysis of PHP

Code

How the Heck did I write so many Bugs?

International PHP Conference Berlin, June 2016

By Rouven Weßling ( ) Ecosystem Developer / Developer Evangelist, Contentful

@RouvenWesslingphoto credit: by Achim Fischer Brandenburg Gate Berlin (license)

Page 2: Static Analysis of PHP Code – IPC Berlin 2016
Page 3: Static Analysis of PHP Code – IPC Berlin 2016

What is StaticAnalysis?

Page 4: Static Analysis of PHP Code – IPC Berlin 2016

Analysing software withoutexecuting it.

Page 5: Static Analysis of PHP Code – IPC Berlin 2016

Dynamic Analysisxdebug

xhprof

PHP Analyzer

PHP Vulnerability Hunter

Assertions

Page 6: Static Analysis of PHP Code – IPC Berlin 2016

Why use StaticAnalysis?

Page 7: Static Analysis of PHP Code – IPC Berlin 2016

Spend less time on unit tests...

Page 8: Static Analysis of PHP Code – IPC Berlin 2016

...and code review

Page 9: Static Analysis of PHP Code – IPC Berlin 2016
Page 10: Static Analysis of PHP Code – IPC Berlin 2016

class ClientTest extends \PHPUnit_Framework_TestCase { public function testGetSynchronizationManager() { $client = new Client('b4c0n73n7fu1', 'cfexampleapi');

$this->assertInstanceOf(Manager::class, $client->getSynchronizationManager()); } }

Page 11: Static Analysis of PHP Code – IPC Berlin 2016

Easy to integrate in ContinuousIntegration

Page 12: Static Analysis of PHP Code – IPC Berlin 2016
Page 13: Static Analysis of PHP Code – IPC Berlin 2016

Find issues that can not be foundthrough unit tests

Page 14: Static Analysis of PHP Code – IPC Berlin 2016

PHP 7

Abstract Syntax TreeScalar TypesStrict Types

Page 15: Static Analysis of PHP Code – IPC Berlin 2016

PHP is dynamic �ReflectionVariable variablesReferencing classes/functions/properties by string

Page 16: Static Analysis of PHP Code – IPC Berlin 2016

The more static your code is, theeasier it's to reason about.

Page 17: Static Analysis of PHP Code – IPC Berlin 2016

Some tools

Page 18: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 19: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 20: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 21: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 22: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 23: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 24: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa php7cc

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 25: Static Analysis of PHP Code – IPC Berlin 2016

phpmd phan phpcs phpunit phploc phpcpd phpsa PHP

Coupling Detector Mondrian PHP

Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHP

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

Page 26: Static Analysis of PHP Code – IPC Berlin 2016

PHP lint

php -l

Page 27: Static Analysis of PHP Code – IPC Berlin 2016
Page 28: Static Analysis of PHP Code – IPC Berlin 2016

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

Page 29: Static Analysis of PHP Code – IPC Berlin 2016

<?php

namespace Contentful\Log

use Psr\Http\Message\RequestInterface;

use Psr\Http\Message\ResponseInterface;

class NullLogger implements LoggerInterface

{

public function getTimer()

{

return new NullTimer;

}

public function log($api, RequestInterface $request, StandardTimer $timer, ResponseInterface $response = null, \Exception $exception = null)

{

}

}

Page 30: Static Analysis of PHP Code – IPC Berlin 2016

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 Contentful\Log

8|

> 9| use Psr\Http\Message\RequestInterface;

10| use Psr\Http\Message\ResponseInterface;

11|

Unexpected 'use' (T_USE), expecting '{'

Page 31: Static Analysis of PHP Code – IPC Berlin 2016

Make your life easierUse PHP-Parallel-Lint

Page 32: Static Analysis of PHP Code – IPC Berlin 2016

Deptrac

Page 33: Static Analysis of PHP Code – IPC Berlin 2016

Software has layersThere should be rules about those layersRules are easily broken

Page 34: Static Analysis of PHP Code – IPC Berlin 2016

1. Define the layers of your architecture2. Define what layers another layer can access3. Profit!!!

Page 35: Static Analysis of PHP Code – IPC Berlin 2016

layers: - name: Controller collectors: - type: className regex: .*Controller.* - name: Entity collectors: - type: className regex: AstaRwth\\VorkursticketBundle\\Entity\\.*

Page 36: Static Analysis of PHP Code – IPC Berlin 2016

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

Page 37: Static Analysis of PHP Code – IPC Berlin 2016

How it works

Parses all files in your codeStores which classes access which others classesChecks the graph for rule violations

Page 38: Static Analysis of PHP Code – IPC Berlin 2016

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.

[...]\Services\PdfOrder::5 must not depend on [...]\Entity\Vorkursticket (Service on Entity)

[...]\Services\PdfOrder::23 must not depend on [...]\Entity\Vorkursticket (Service on Entity)

Found 2 Violations

Page 39: Static Analysis of PHP Code – IPC Berlin 2016
Page 40: Static Analysis of PHP Code – IPC Berlin 2016

phan

Page 41: Static Analysis of PHP Code – IPC Berlin 2016
Page 42: Static Analysis of PHP Code – IPC Berlin 2016

Type safety for PHP

Checks docblocks

Signature mismatches

Unused code

Page 43: Static Analysis of PHP Code – IPC Berlin 2016

How it works

Makes 2 passes over the codebase1. Build a list of all classes, functions, methods, etc.2. Go trough each function and follow the type ofeach variable

Page 44: Static Analysis of PHP Code – IPC Berlin 2016

/** * @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

Page 45: Static Analysis of PHP Code – IPC Berlin 2016

class ContentType { /** * The fields, keyed by ID. * * @var object */ private $fields = []; }

src/Delivery/ContentType.php:34 PhanTypeMismatchProperty Assigning array to property but \contentful\delivery\contenttype::fields is object

Page 46: Static Analysis of PHP Code – IPC Berlin 2016

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 \contentful\delivery\link but \array_map() takes array

Not a bug

Page 47: Static Analysis of PHP Code – IPC Berlin 2016

Not a bug

Don't trust blindly

Page 48: Static Analysis of PHP Code – IPC Berlin 2016

Bad news?Requires php-astNot easy to deal with library codeNoisy - not easily integrated in CI.

Page 49: Static Analysis of PHP Code – IPC Berlin 2016

The future

Page 50: Static Analysis of PHP Code – IPC Berlin 2016

phan is using brute force for type checkingRoughly as good as the compiler for a staticallytyped languageWorks, but a Control Flow Graph could give evendeeper insight

Page 51: Static Analysis of PHP Code – IPC Berlin 2016

int foo(int length) { int x = 0; for (int i = 0; i < length; i++) x += 1

return length/x; }

Page 52: Static Analysis of PHP Code – IPC Berlin 2016
Page 53: Static Analysis of PHP Code – IPC Berlin 2016

Bottom lineThere are dozens of tools - pick what's necessary foryouMake them part of your Continuous Integration setupNever trust. Make sure you understand where theerror is coming from.

Page 54: Static Analysis of PHP Code – IPC Berlin 2016

Slides available on Slideshare:http://www.slideshare.net/rwessling/static-analysis-of-

php-code-ipc-berlin-2016