Static C/C++ analysis with PVS-Studio
This blog post goes over how a student can statically analyze their C/C++ code with PVS-Studio for free on Ubuntu.
The PVS-Studio team wrote a fascinating post called 100 bugs in Open Source C/C++ projects, which I highly recommend checking out.
Setup
- Install pvs-studio on Ubuntu from the App Center (or using the PVS-Studio installation page for students)
- Run
pvs-studio-analyzer credentials PVS-Studio Free FREE-FREE-FREE-FREE
to activate a free student license - Add this comment to the top of your C file:
// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: https://pvs-studio.com
Usage
// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: https://pvs-studio.com
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *foo = malloc(sizeof(int));
*foo = 42;
printf("%d\n", *foo);
free(foo);
}
Compiling this program with lots of warnings turned on and fsanitize makes it seem like the program works fine, since it prints 42
successfully:
clang foo.c -Wall -Wextra -Werror -Wpedantic -fsanitize=address,undefined && ./a.out
But there’s actually a bug in this function. Let’s use PVS-Studio to find it for us!
- Generate
strace_out
withpvs-studio-analyzer trace -- gcc foo.c
- Generate
pvs.log
withpvs-studio-analyzer analyze -o pvs.log
- Generate
pvs.json
withplog-converter -a GA:1,2 -t json -o pvs.json pvs.log
(runplog-converter --help
to get descriptions of these flags)
If you install the PVS-Studio extension for VS Code, you should see this PVS-STUDIO
tab appear in the bottom panel (if you don’t see it, refer to the extension’s official PVS-Studio guide):
Inside of the PVS-STUDIO
tab, click the Open report
button, and select the pvs.json
file we generated. You should now see this:
It warns about lines 8 and 10, which correspond to the malloc()
and *foo = 42;
lines.
The message There might be dereferencing of a potential null pointer 'foo'
is completely correct, and we can resolve it by adding this right after the malloc()
call:
if (!foo) {
return EXIT_FAILURE;
}