Why does Cppcheck not find this obvious array out-of-bounds error?
Asked Answered
M

3

7

I installed the Cppcheck tool for static code analysis of my C++ project and got the feeling that it performs poorly. For example, can anyone tell me why Cppcheck is unable to find an array out-of-bounds error in the following code?

void f(int c) { 
    char *p = new char[10]; 
    p[c] = 42; 
} 

void g() { 
    f(100); 
} 

There's an online demo where this code can be conveniently checked using Cppcheck. All it comes up with is a memory leak at line 4, no signs of a potential buffer overflow.

Marianamariand answered 15/8, 2012 at 9:4 Comment(4)
I notice that your question has already been posted and commented on in the cppcheck forum. The comment there seems to imply that this type of bounds checking isn't supported yet. It might be better to question this further in that forum.Caiaphas
because no tool could ever find all errors, and especially cppcheck does not fully parse and evaluate c++, but contains lots of shortcuts that allow only for most local errors to be detected.Nitza
Describe the steps needed for the tool to be able to detect the error. Then enumerate the cases where false positives would pop up. Then have a go at imagining the developers sitting down and weighing these things against each other.Spieler
Yeah well, I wasn't too happy with cppcheck either when I tried it. Might try again when I have more code to check, though :-) Either way, what kind of answer do you expect? cppcheck doesn't find your bug simply "because it doesn't check for that particular combination of things". A cppcheck developer might be able to explain whether they just forgot that case, or whether it takes more than a one-line change to cppcheck, or even a fundamental change to a module, but the fact remains that it's not done. "Obvious" is a very dangerous word... software has a very different concept of "obvious" :-)Batch
B
9

Because it is not supported currently.

This is actually not an obvious error to the compiler. Something like

char c[5];
for (int i=0; i<10; ++i)
    c[i] = 0;

is more obvious, as it is all in the same code.

Something like

#define f(c) { \
    char *p = new char[10];  \
    p[c] = 42; \
}

void g() { 
    f(100); 
} 

is more obvious, because cppcheck and the compiler expand all macros in-place before actual checks.

However, your posted code is not trivial, because cppcheck as well as the compiler need the whole code inside that function and evaluate it with respect to the parameter. It is of course possible if the function is in sight (it becomes pretty hard, up to impossible, across translation units), but right now, cppcheck does not have that feature.

Borges answered 15/8, 2012 at 9:37 Comment(0)
B
10

I am a Cppcheck developer.

It is not by design that Cppcheck fail to detect that.

Cppcheck currently doesn't evaluate functions using all given parameters from all function calls. We have tickets about this and I hope it will be fixed someday. It would be nice.

If you use Cppcheck you should not think that it will detect all bugs. Cppcheck will probably fail to detect most bugs. There is no method in my humble opinion that will detect all bugs in your software. Use Cppcheck just to detect some of the bugs that you fail to detect otherwise. It reduce the number of bugs somewhat.

I hope you are not too disappointed and will continue to use Cppcheck.

Brainwash answered 15/8, 2012 at 19:40 Comment(2)
Sorry, but it is by design that CppCheck fails to detect OP's problem. CppCheck is designed to produce a stream of langauge tokens, and apply "patterns" to check token sequences for problems. But a tokenizer has no real understanding of the type information in the language and thus can't do any "type" related checking. Of course, with sufficient energy, one could add all that type information by processing the tokens, but by then you have full featured C++ front end and that doesn't appear to be in CppCheck's ambition. This tool simply cannot go very far in serious static analysis.Captivate
I'm not disappointed in Cppcheck, it is a great open source project. I just did not know its limitations well enough. Thanks for the explanations.Marianamariand
B
9

Because it is not supported currently.

This is actually not an obvious error to the compiler. Something like

char c[5];
for (int i=0; i<10; ++i)
    c[i] = 0;

is more obvious, as it is all in the same code.

Something like

#define f(c) { \
    char *p = new char[10];  \
    p[c] = 42; \
}

void g() { 
    f(100); 
} 

is more obvious, because cppcheck and the compiler expand all macros in-place before actual checks.

However, your posted code is not trivial, because cppcheck as well as the compiler need the whole code inside that function and evaluate it with respect to the parameter. It is of course possible if the function is in sight (it becomes pretty hard, up to impossible, across translation units), but right now, cppcheck does not have that feature.

Borges answered 15/8, 2012 at 9:37 Comment(0)
A
4

The latest version of Cppcheck 1.70 dev is able to detect this bug:

$ cppcheck test.cpp 
Checking test.cpp...
[test.cpp:3]: (error) Array 'p[10]' accessed at index 100, which is out of bounds.
[test.cpp:4]: (error) Memory leak: p
Arse answered 19/6, 2015 at 6:22 Comment(2)
Does this example have the function in the same file or does it work with the function in one file and the call to the function in another file?Mitchelmitchell
This is a good point. According to my tests here, the buffer access out of bounds issue is only detected by cppcheck if the code resides in the same file.Arse

© 2022 - 2024 — McMap. All rights reserved.