Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent returning a pointer to a temporary variable?

On a recent bug hunt, I found an issue with returning a pointer to a member of a temporary variable. The offending (simplified) code was:

struct S {
    S(int i) : i(i) {}
    int i;
    int* ptr() { return &i; }
};

int* fun(int i) { return S(i).ptr(); }  // temporary S dies but pointer lives on

int main() {
    int* p = fun(1);
    return *p;  // undefined
}

How to prevent this? GCC & Clang have -Waddress-of-temporary and -Wreturn-stack-address but they seem to loose trail because of ptr() acting as a middle man for the dirty deeds. They are only triggered when the pointer is taken directly:

int* fun(int i) { return &S(i).i; }  // rightly fails to compile

My project also incorporates cppcheck in continuous integration but it also can't pick it up (raised here).

Which static analysis tool can prevent this class of bugs?

EDIT: GCC does pick it up since version 6.1.0 with -Wreturn-local-addr and (surprisingly) -O2 switched on.

like image 475
Tomek Sowiński Avatar asked Nov 08 '16 21:11

Tomek Sowiński


People also ask

Why we should not return a pointer to a local variable?

The return statement should not return a pointer that has the address of a local variable ( sum ) because, as soon as the function exits, all local variables are destroyed and your pointer will be pointing to someplace in the memory that you no longer own.

Can we return pointer to a local variable?

We can pass pointers to the function as well as return pointer from a function. But it is not recommended to return the address of a local variable outside the function as it goes out of scope after function returns.

What is the correct way of declaring a pointer and using it?

Pointers must be declared before they can be used, just like a normal variable. The syntax of declaring a pointer is to place a * in front of the name. A pointer is associated with a type (such as int and double ) too.

How to define a pointer variable in c++?

Create a pointer variable with the name ptr , that points to a string variable, by using the asterisk sign * ( string* ptr ). Note that the type of the pointer has to match the type of the variable you're working with.


1 Answers

I am a Cppcheck developer.

My project also incorporates cppcheck in continuous integration but it also can't pick it up.

interesting bug. This is the kind of bug that cppcheck wants to warn about. We have some related checks but this slipped through unfortunately.

Not really surprising given the regex nature of cppcheck.

I don't personally understand why some people say cppcheck is a regex tool.

It uses AST, context sensitive valueflow analysis, etc to detect bugs. So does GCC and Clang. Cppcheck is sometimes claimed to be a regex tool but GCC and Clang are not.

like image 126
Daniel Marjamäki Avatar answered Oct 04 '22 13:10

Daniel Marjamäki