From code review to static code analysis. Static code analysis techniques. Some examples of defects in real projects. C, C++, C#, Java.
Size: 2.33 MB
Language: en
Added: Jun 15, 2021
Slides: 36 pages
Slide Content
Static code analysis: what ? how ? why ? Maxim Stefanov PVS-Studio, C++ / Java developer, Tula 1
About The Speaker Maxim Stefanov ( [email protected] ) C++/Java developer in PVS-Studio Duties: Develops C++ core of the analyzer Develops Java analyzer 2
Theory The importance of code quality ( bugs , vulnerabilities, ... ) Defect prevention methods From code review to static code analysis Code review VS Static code analysis Static code analysis techniques Some examples of defects in real projects More about static analysis Summary 3 We’ll Talk About ...
Perception Enhancement Support Absence of bugs ... et cetera 4 High-Quality Code
It prevents technical debt if the project is new It helps not to lose users if the project is mature 5 Why Is Code Quality Important?
Cost to Fix a Defect
Helps to find high-level bugs without shooting yourself in the foot Allows to share experience with padawans Together you’ll learn some new things about the project and its secrets 7 Code review
Code review is very expensive : Expectation : « We’ll review this edit for 10-15 min » Reality – sometimes code review takes hours You get tired quickly 8 But ...
Pros Cons Finds defects before code review You can’t find high-level errors An analyzer can’t get tired, it’s ready to work at any time False positives You can find errors without even knowing about such a pattern You can find errors which are difficult to notice 9 Static Code Analysis Comes to Rescue
P attern-based analysis Type inference Method annotations D ata-flow analysis Symbolic execution 10 Static Code Analysis Techniques
Type inference interface Human { ... . } class Parent implements Human { .. . . } class Child extends Parent { ... . } .... class Animal { ... } .... boolean someMethod ( List < Child > list , Animal animal ) { if ( list.remove ( animal ) ) return false ; .. . . } 12
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 13
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 14
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 15
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 16
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 17
Method annotations Class (" java.lang.Math " ) - Function ( " max " , Type ::Int32, Type ::Int32) . Pure () . Set ( FunctionClassification :: NoDiscard ) . Requires ( NotEquals (Arg1, Arg2)) . Returns (Arg1, Arg2,[]( const Int &v1, const Int &v2) { return v1.Max(v2); }) 18
int test ( int a, int b) { .... Math. max (a, b ); .... } 19 Method annotations
int test ( int a, int b) { .... return Math. max (a, a) ; } 20 Method annotations
int test ( int a, int b) { if (a > 5 && b < 2) { // a = [6..INT_MAX] // b = [INT_MIN..1] if ( Math. max (a, b) > 0 ) { ....} } .... } 21 Method annotations
V778 Two similar code fragments were found. Perhaps, this is a typo and ' cap_resy ' variable should be used instead of ' cap_resx '. cyapa.c 1458 Copy Paste static int cyapa_raw_input ( struct cyapa_softc * sc , ....) { .... if ( sc -> delta_x > sc -> cap_resx ) sc -> delta_x = sc -> cap_resx ; if ( sc -> delta_x < - sc -> cap_resx ) sc -> delta_x = - sc -> cap_resx ; if ( sc -> delta_y > sc -> cap_resx ) sc -> delta_y = sc -> cap_resy ; if ( sc -> delta_y < - sc -> cap_resy ) sc -> delta_y = - sc -> cap_resy ; .... } 28 FreeBSD Kernel , C
V778 Two similar code fragments were found. Perhaps, this is a typo and ' cap_resy ' variable should be used instead of ' cap_resx '. cyapa.c 1458 Copy Paste static int cyapa_raw_input ( struct cyapa_softc * sc , ....) { .... if ( sc -> delta_ x > sc -> cap_res x ) sc -> delta_ x = sc -> cap_res x ; if ( sc -> delta_ x < - sc -> cap_res x ) sc -> delta_ x = - sc -> cap_res x ; if ( sc -> delta_ y > sc -> cap_res x ) sc -> delta_ y = sc -> cap_res y ; if ( sc -> delta_ y < - sc -> cap_res y ) sc -> delta_ y = - sc -> cap_res y ; .... } 29 FreeBSD Kernel , C
char c; printf( "%s .... "); rewind( blk_alloc_file ); while ( (c = fgetc ( blk_alloc_file )) != EOF ) { fputc (c, base_fs_file ); } Android , C PVS-Studio: V739 CWE-20 EOF should not be compared with a value of the 'char' type. The '(c = fgetc ( blk_alloc_file ))' should be of the ' int ' type. blk_alloc_to_base_fs.c 61 30 Unlucky Character
Compiler Deletes Code to Wipe Buffer static void FwdLockGlue_InitializeRoundKeys () { unsigned char keyEncryptionKey [KEY_SIZE]; .... memset ( keyEncryptionKey , 0, KEY_SIZE); // Zero out key data. } PVS-Studio: V597 CWE-14 The compiler could delete the ' memset ' function call , which is used to flush ' keyEncryptionKey ' buffer . The memset_s () function should be used to erase the private data . FwdLockGlue.c 102 31 Android , C
How to Blend Static Analysis into Software Development Process Every developer has a static analysis tool in their workplace Analysis of the entire codebase during night builds. If suspicious code is found, the guilty one will receive an email 32
How to Start Using Static Analysis Tools in Big Projects and Keep Your Cool Check the project Put all issued warnings in a special suppression file to indicate that now you are not interested in all issued warnings Put the markup file into the version control system Run the analyzer and receive warnings only for new or changed code PROFIT! 33
Summary Static analysis helps to immediately find some errors while the cost to fix them is low Static analysis should be used regularly You can start using the analysis right away and fix some old errors after Static analysis is not a silver bullet, it’s important to use different techniques 34
Thank you for your attention ! 35
Useful Links The podcast about static analysis with PVS-Studio founders [RU] The list of static analysis tools The PVS-Studio site