Static Analyze Tool: Clang Static Analyze

这是同济大学 2019春软件测试的作业,我把涉及的东西放到这里。


Clang Static Analyzer

This folder use clang analyze to do static code analyze. And we use both valgrind to test the correctness of clang analysis.

The code is used to test the bug or code style, so the code maybe dirty, un-safe and obey the coding style.

You can see clang-analyze here: https://clang-analyzer.llvm.org/

config

First, you should install from the home page of Clang Static Analyzer: https://clang-analyzer.llvm.org/

sudo tar -jxvf /Users/fuasahi/Downloads/checker-279.tar.bz2 -C /usr/local

Then write data to ~/.zshrc

echo 'export PATH="$PATH:/usr/local/checker-279/bin"' >> ~/.zshrc

After install, I wrote a memory_leak.c

//
// Created by 付旭炜 on 2019/3/19.
//
#include <stdlib.h>
#include <stdio.h>
int **m_value_no_return(int size) {
int **darr = (int**) malloc(sizeof(int**) * size);
for (int i = 0; i < size; ++i) {
darr[i] = malloc(sizeof(int*));
}
return darr;
}
int main() {
// memory leak
int *p = (int *)malloc(sizeof(int));
*p = 32;
printf("%d\n", *p);
free(p);
// chkeck size
int a[10];
// a[10] = 123;
// different types
a[5] = 'a';
int ** mlc = m_value_no_return(5);
// free(mlc);
return 0;
}

When I run :

scan-build gcc -c memory_leak.c -o memory-leak

Below is what I got:

scan-build: Using '/usr/local/checker-279/bin/clang' for static analysis
memory_leak.c:9:26: warning: Result of 'malloc' is converted to a pointer of type 'int *', which is incompatible with sizeof operand type 'int **'
int **darr = (int**) malloc(sizeof(int**) * size);
~~~~~~ ^~~~~~ ~~~~~~~~~~~~~
memory_leak.c:11:19: warning: Result of 'malloc' is converted to a pointer of type 'int', which is incompatible with sizeof operand type 'int *'
darr[i] = malloc(sizeof(int*));
^~~~~~ ~~~~~~~~~~~~
memory_leak.c:30:12: warning: Value stored to 'mlc' during its initialization is never read
int ** mlc = m_value_no_return(5);
^~~ ~~~~~~~~~~~~~~~~~~~~
3 warnings generated.
scan-build: 3 bugs found.
scan-build: Run 'scan-view /var/folders/nx/x90btfys6ln48h5pdy7673bc0000gn/T/scan-build-2019-03-19-222512-26783-1' to examine bug reports.

run single sourcefile

There is a core.c, containing some warnings Static Analyze should issue. Let’s compile it:

scan-build gcc core.c -o core

Output is:

scan-build: Using '/usr/local/checker-279/bin/clang' for static analysis
core.c:21:5: warning: Called function pointer is an uninitialized pointer value
foo(); // warn: function pointer is uninitialized
^~~~~
core.c:27:9: warning: Value stored to 'x' is never read
x = 1 / z; // warn
^ ~~~~~
core.c:27:15: warning: Division by zero
x = 1 / z; // warn
~~^~~
core.c:32:5: warning: Value stored to 'x' is never read
x = 1; // warn
^ ~
4 warnings generated.
scan-build: 4 bugs found.
scan-build: Run 'scan-view /var/folders/nx/x90btfys6ln48h5pdy7673bc0000gn/T/scan-build-2019-03-20-003918-31501-1' to examine bug reports.

All the bugs in system was issued.

run project

cd project/build
cmake ..
scan-build make

Now you can build the whole project.

memory leak

# mwish @ fxwuueis-mbp in ~/ClionProjects/cpp-learning/clang_check on git:master x [0:39:19]
$ scan-build gcc leak_demo.c -o leak-demo -Wall
scan-build: Using '/usr/local/checker-279/bin/clang' for static analysis
scan-build: Removing directory '/var/folders/nx/x90btfys6ln48h5pdy7673bc0000gn/T/scan-build-2019-03-20-004638-31675-1' because it contains no reports.
scan-build: No bugs found.

So, as you can see there is no warning, but when we use valgrind, we can see:

# mwish @ fxwuueis-mbp in ~/ClionProjects/cpp-learning/clang_check on git:master x [0:46:38]
$ valgrind ./leak-demo
==31703== Memcheck, a memory error detector
==31703== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31703== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==31703== Command: ./leak-demo
==31703==
--31703-- run: /usr/bin/dsymutil "./leak-demo"
warning: no debug symbols in executable (-arch x86_64)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57
0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95
0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 114
0 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105 112 119 126 133
0 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 128 136 144 152
0 9 18 27 36 45 54 63 72 81 90 99 108 117 126 135 144 153 162 171
0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190
0 11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 176 187 198 209
0 12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 192 204 216 228
0 13 26 39 52 65 78 91 104 117 130 143 156 169 182 195 208 221 234 247
0 14 28 42 56 70 84 98 112 126 140 154 168 182 196 210 224 238 252 266
0 15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255 270 285
0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 272 288 304
0 17 34 51 68 85 102 119 136 153 170 187 204 221 238 255 272 289 306 323
0 18 36 54 72 90 108 126 144 162 180 198 216 234 252 270 288 306 324 342
0 19 38 57 76 95 114 133 152 171 190 209 228 247 266 285 304 323 342 361
==31703==
==31703== HEAP SUMMARY:
==31703== in use at exit: 24,509 bytes in 187 blocks
==31703== total heap usage: 209 allocs, 22 frees, 33,117 bytes allocated
==31703==
==31703== LEAK SUMMARY:
==31703== definitely lost: 1,600 bytes in 20 blocks
==31703== indirectly lost: 0 bytes in 0 blocks
==31703== possibly lost: 72 bytes in 3 blocks
==31703== still reachable: 200 bytes in 6 blocks
==31703== suppressed: 22,637 bytes in 158 blocks
==31703== Rerun with --leak-check=full to see details of leaked memory
==31703==
==31703== For counts of detected and suppressed errors, rerun with: -v
==31703== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

Here, we lost some malloc memory!