For a good introduction to "Static Analysis" take a look at http://www.altdevblogaday.com/2011/12/24/static-code-analysis/ where John Carmack present a review of several existing tools.
But here I try to explain why sometimes a good compiler like GCC "can" act as a static code checker. To demonstrate and explain it, lets talk about the code below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <iostream> #include <string> //inline int func(int tab[], bool toSwitch) //force inline. //__attribute__ ((noinline)) int func(int tab[], bool toSwitch) //prevent inline. int func(int tab[], int idx) //let compiler inline based on its own logic and optimization parameters. { return tab[idx]; } int main(int argc, char* argv[]) { std::cout << argc << " " << std::string(argv[0]) << std::endl; int myTab[4] = {1,2,3,4}; //int myTab[10] = {1,2,3,4,5,6,7,8,9,10}; std::cout << func(myTab, 0) << std::endl; std::cout << func(myTab, 8) << std::endl; //At least the line is detected by VS'12 Static Analyzer.... std::cout << myTab[8] << std::endl; return 0; } |
I mainly code using Visual Studio IDE (08,10 at work and 12 at home for now...) but hopefully i also use GCC and we will see why just below. As you can see, i coded 2 buffer overrun by calling "func(myTab, 8)" and "myTab[8]".
- Visual Studio 2012
//At least the line is detected by VS'12 Static Analyzer.... std::cout << myTab[8] << std::endl;
stl_usage.cpp(22): warning : C6201: Index '8' is out of valid index range '0' to '3' for possibly stack allocated buffer 'myTab'.
stl_usage.cpp(22): warning : C6385: Reading invalid data from 'myTab': the readable size is '16' bytes, but '36' bytes may be read.
- GCC
g++ -Wall -Wextra -Werror -O3 ./gcc-static-analys.cpp
I got the following error:
./gcc-static-analys.cpp: In function âint main(int, char**)â:
./gcc-static-analys.cpp:17: error: âmyTab[8]â is used uninitialized in this function [-Werror=uninitialized]
./gcc-static-analys.cpp:20: error: âmyTab[8]â is used uninitialized in this function [-Werror=uninitialized]
cc1plus: all warnings being treated as errors
But why GCC can detect these 2 buffer overrun at compile-time. For the direct and invalid access to myTab[8] it should be easy but for "func(8)", it's a bit tricky. In fact if you had a look at the 2 comment line 4 and 5, you may have guess that it's mainly come from the "inlining" of "func".
Depending of the optimization level you used GCC can decide to inline some function by itself and in fact case he can detect some error and act as a Stactic Analyzer preventing use to let something wrong (a security issue) in our code.