Static code analysis: what? how? why?
- 2. About The Speaker
• Maxim Stefanov (stefanov@viva64.com)
• C++/Java developer in PVS-Studio
• Duties:
• Develops C++ core of the analyzer
• Develops Java analyzer
2
- 3. • 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...
- 5. •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?
- 7. •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
- 8. •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...
- 9. 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
- 11. @Override
public boolean equals(Object obj) {
....
return index.equals(other.index)
&& type.equals(other.type)
&& version == other.version
&& found == other.found
&& tookInMillis == tookInMillis
&& Objects.equals(terms, other.terms);
}
11
Pattern-based analysis
- 12. 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
- 19. int test(int a, int b) {
....
Math.max(a, b);
....
}
19
Method annotations
- 20. int test(int a, int b)
{
....
return Math.max(a, a);
}
20
Method annotations
- 21. 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
- 22. Data-flow analysis
void func(int x) {
// x: [-2147483648..2147483647] //1
if (x > 3) {
// x: [4..2147483647] //2
if (x < 10) {
// x: [4..9] //3
}
} else {
// x: [-2147483648..3] //4
}
}
22
- 25. PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header,
uintptr_t header_mask, int value)
{
char buf[128];
sprintf(buf, "%d", value);
return set_value_buffer(dest, header, header_mask, buf);
}
StarEngine, C++
PVS-Studio: V614 Uninitialized buffer 'buf' used. pugixml.cpp 3362
It Came Up Unexpectedly...
25
- 26. It Came Up Unexpectedly...
PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header,
uintptr_t header_mask, int value)
{
char buf[128];
sprintf(buf, "%d", value);
return set_value_buffer(dest, header, header_mask, buf);
}
PVS-Studio: V614 Uninitialized buffer 'buf' used. pugixml.cpp 3362
#define schar char
#define suchar unsigned schar
#define sprintf std::printf
#define satof atof
#define satoi atoi
26
StarEngine, C++
- 27. PVS-Studio: V6007 Expression 'StringUtils.isNotEmpty("handleTabKey")' is always true.
SourceCodeEditorLoader.java 60
Copy Paste
public void loadComponent() {
....
String handleTabKey = element.attributeValue("handleTabKey");
if (StringUtils.isNotEmpty("handleTabKey")) {
resultComponent.setHandleTabKey(....);
}
....
}
27
CUBA Platform, Java
- 28. 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
- 29. 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;
....
}
29
FreeBSD Kernel, C
- 30. 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
- 31. 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
- 32. 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
- 33. How to Start Using Static Analysis Tools in Big
Projects and Keep Your Cool
1. Check the project
2. Put all issued warnings in a special suppression file to indicate that
now you are not interested in all issued warnings
3. Put the markup file into the version control system
4. Run the analyzer and receive warnings only for new or changed
code
5. PROFIT!
33
- 34. 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
- 36. Useful Links
The podcast about static analysis
with PVS-Studio founders [RU]
The list of static analysis tools
The PVS-Studio site