2010-10-31 11:51:25 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2019-02-09 07:24:06 +01:00
* Copyright ( C ) 2007 - 2019 Cppcheck team .
2010-10-31 11:51:25 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "checknullpointer.h"
2018-12-18 07:56:33 +01:00
# include "checkuninitvar.h"
2017-05-27 04:33:47 +02:00
# include "library.h"
# include "settings.h"
2010-10-31 11:51:25 +01:00
# include "testsuite.h"
2017-05-27 04:33:47 +02:00
# include "token.h"
# include "tokenize.h"
2017-05-18 21:52:31 +02:00
# include <simplecpp.h>
2017-05-27 04:33:47 +02:00
# include <tinyxml2.h>
# include <list>
# include <map>
# include <string>
# include <vector>
2010-10-31 11:51:25 +01:00
2011-10-13 20:53:06 +02:00
class TestNullPointer : public TestFixture {
2010-10-31 11:51:25 +01:00
public :
2014-11-20 14:20:09 +01:00
TestNullPointer ( ) : TestFixture ( " TestNullPointer " ) {
2013-08-07 16:27:37 +02:00
}
2010-10-31 11:51:25 +01:00
private :
2014-03-24 09:59:05 +01:00
Settings settings ;
2010-10-31 11:51:25 +01:00
2019-01-12 15:45:25 +01:00
void run ( ) OVERRIDE {
2019-03-17 07:37:38 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2015-10-07 18:33:57 +02:00
settings . addEnabled ( " warning " ) ;
2014-03-24 09:59:05 +01:00
2011-10-09 15:09:02 +02:00
TEST_CASE ( nullpointerAfterLoop ) ;
2010-10-31 11:51:25 +01:00
TEST_CASE ( nullpointer1 ) ;
TEST_CASE ( nullpointer2 ) ;
2010-11-04 18:18:19 +01:00
TEST_CASE ( structDerefAndCheck ) ; // dereferencing struct and then checking if it's null
TEST_CASE ( pointerDerefAndCheck ) ;
2010-10-31 11:51:25 +01:00
TEST_CASE ( nullpointer5 ) ; // References should not be checked
2010-12-26 13:38:16 +01:00
TEST_CASE ( nullpointerExecutionPaths ) ;
TEST_CASE ( nullpointerExecutionPathsLoop ) ;
2010-10-31 11:51:25 +01:00
TEST_CASE ( nullpointer7 ) ;
TEST_CASE ( nullpointer9 ) ;
2011-05-28 05:30:19 +02:00
TEST_CASE ( nullpointer10 ) ;
2011-06-04 04:16:08 +02:00
TEST_CASE ( nullpointer11 ) ; // ticket #2812
2011-10-16 12:54:58 +02:00
TEST_CASE ( nullpointer12 ) ; // ticket #2470
2012-01-28 08:06:03 +01:00
TEST_CASE ( nullpointer15 ) ; // #3560 (fp: return p ? f(*p) : f(0))
2012-02-13 19:46:45 +01:00
TEST_CASE ( nullpointer16 ) ; // #3591
2012-03-07 20:31:23 +01:00
TEST_CASE ( nullpointer17 ) ; // #3567
2012-04-01 15:56:48 +02:00
TEST_CASE ( nullpointer18 ) ; // #1927
2012-05-16 09:56:39 +02:00
TEST_CASE ( nullpointer19 ) ; // #3811
2012-05-31 18:41:00 +02:00
TEST_CASE ( nullpointer20 ) ; // #3807 (fp: return p ? (p->x() || p->y()) : z)
2012-09-23 09:20:16 +02:00
TEST_CASE ( nullpointer21 ) ; // #4038 (fp: if (x) p=q; else return;)
2013-03-19 08:47:05 +01:00
TEST_CASE ( nullpointer23 ) ; // #4665 (false positive)
2013-10-20 13:37:36 +02:00
TEST_CASE ( nullpointer24 ) ; // #5082 fp: chained assignment
2014-03-26 12:17:27 +01:00
TEST_CASE ( nullpointer25 ) ; // #5061
2014-03-27 19:16:30 +01:00
TEST_CASE ( nullpointer26 ) ; // #3589
2019-05-16 21:11:04 +02:00
TEST_CASE ( nullpointer27 ) ; // #6568
2015-08-15 00:31:26 +02:00
TEST_CASE ( nullpointer28 ) ; // #6491
2015-08-15 01:00:36 +02:00
TEST_CASE ( nullpointer30 ) ; // #6392
2018-04-09 16:13:17 +02:00
TEST_CASE ( nullpointer31 ) ; // #8482
2018-11-03 15:53:24 +01:00
TEST_CASE ( nullpointer32 ) ; // #8460
2015-01-05 14:54:24 +01:00
TEST_CASE ( nullpointer_addressOf ) ; // address of
2014-03-28 10:06:24 +01:00
TEST_CASE ( nullpointerSwitch ) ; // #2626
2013-04-03 10:27:08 +02:00
TEST_CASE ( nullpointer_cast ) ; // #4692
2012-04-30 12:36:41 +02:00
TEST_CASE ( nullpointer_castToVoid ) ; // #3771
2011-10-12 22:11:27 +02:00
TEST_CASE ( pointerCheckAndDeRef ) ; // check if pointer is null and then dereference it
TEST_CASE ( nullConstantDereference ) ; // Dereference NULL constant
TEST_CASE ( gcc_statement_expression ) ; // Don't crash
2011-06-26 21:46:33 +02:00
TEST_CASE ( snprintf_with_zero_size ) ;
TEST_CASE ( snprintf_with_non_zero_size ) ;
2011-10-12 22:11:27 +02:00
TEST_CASE ( printf_with_invalid_va_argument ) ;
TEST_CASE ( scanf_with_invalid_va_argument ) ;
2011-10-23 23:36:57 +02:00
TEST_CASE ( nullpointer_in_return ) ;
2011-11-04 09:49:49 +01:00
TEST_CASE ( nullpointer_in_typeid ) ;
2011-11-07 21:10:21 +01:00
TEST_CASE ( nullpointer_in_for_loop ) ;
2011-11-13 22:35:13 +01:00
TEST_CASE ( nullpointerDelete ) ;
2011-11-23 21:19:54 +01:00
TEST_CASE ( nullpointerExit ) ;
2012-01-25 15:16:22 +01:00
TEST_CASE ( nullpointerStdString ) ;
2012-03-16 17:24:03 +01:00
TEST_CASE ( nullpointerStdStream ) ;
2019-04-26 11:30:09 +02:00
TEST_CASE ( nullpointerSmartPointer ) ;
2011-12-25 17:01:45 +01:00
TEST_CASE ( functioncall ) ;
2013-07-15 21:57:58 +02:00
TEST_CASE ( functioncalllibrary ) ; // use Library to parse function call
2012-11-21 08:56:17 +01:00
TEST_CASE ( functioncallDefaultArguments ) ;
2013-10-12 10:50:59 +02:00
TEST_CASE ( nullpointer_internal_error ) ; // #5080
2015-07-31 21:15:43 +02:00
TEST_CASE ( ticket6505 ) ;
2016-10-09 15:15:29 +02:00
TEST_CASE ( subtract ) ;
2018-04-03 21:32:37 +02:00
TEST_CASE ( addNull ) ;
2018-12-18 07:56:33 +01:00
TEST_CASE ( ctu ) ;
2010-10-31 11:51:25 +01:00
}
2015-07-25 14:17:55 +02:00
void check ( const char code [ ] , bool inconclusive = false , const char filename [ ] = " test.cpp " ) {
2010-10-31 11:51:25 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2011-10-09 15:09:02 +02:00
settings . inconclusive = inconclusive ;
2014-01-12 19:27:26 +01:00
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2012-08-25 12:00:25 +02:00
if ( ! tokenizer . tokenize ( istr , filename ) )
2012-08-12 12:01:24 +02:00
return ;
2010-12-01 18:00:55 +01:00
2017-05-15 20:05:11 +02:00
// Check for null pointer dereferences..
2016-10-09 15:15:29 +02:00
CheckNullPointer checkNullPointer ;
checkNullPointer . runChecks ( & tokenizer , & settings , this ) ;
2010-10-31 11:51:25 +01:00
}
2017-05-18 21:52:31 +02:00
void checkP ( const char code [ ] ) {
// Clear the error buffer..
errout . str ( " " ) ;
settings . inconclusive = false ;
// Raw tokens..
2018-04-09 09:41:24 +02:00
std : : vector < std : : string > files ( 1 , " test.cpp " ) ;
2017-05-18 21:52:31 +02:00
std : : istringstream istr ( code ) ;
const simplecpp : : TokenList tokens1 ( istr , files , files [ 0 ] ) ;
// Preprocess..
simplecpp : : TokenList tokens2 ( files ) ;
std : : map < std : : string , simplecpp : : TokenList * > filedata ;
simplecpp : : preprocess ( tokens2 , tokens1 , files , filedata , simplecpp : : DUI ( ) ) ;
// Tokenizer..
Tokenizer tokenizer ( & settings , this ) ;
tokenizer . createTokens ( & tokens2 ) ;
tokenizer . simplifyTokens1 ( " " ) ;
// Check for null pointer dereferences..
CheckNullPointer checkNullPointer ;
checkNullPointer . runChecks ( & tokenizer , & settings , this ) ;
}
2010-10-31 11:51:25 +01:00
2014-11-20 14:20:09 +01:00
void nullpointerAfterLoop ( ) {
2010-10-31 11:51:25 +01:00
check ( " int foo(const Token *tok) \n "
" { \n "
" while (tok); \n "
" tok = tok->next(); \n "
2014-09-04 17:52:14 +02:00
" } " , true ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok. \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-03-28 19:27:07 +02:00
// #2681
2011-10-18 19:34:14 +02:00
{
const char code [ ] = " void foo(const Token *tok) \n "
" { \n "
" while (tok && tok->str() == \" = \" ) \n "
" tok = tok->next(); \n "
" \n "
" if (tok->str() != \" ; \" ) \n "
" ; \n "
" } \n " ;
check ( code , false ) ; // inconclusive=false => no error
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( code , true ) ; // inconclusive=true => error
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:6]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok. \n " , errout . str ( ) ) ;
2011-10-18 19:34:14 +02:00
}
2011-03-28 19:27:07 +02:00
2010-10-31 11:51:25 +01:00
check ( " void foo() \n "
" { \n "
" for (const Token *tok = tokens; tok; tok = tok->next()) \n "
" { \n "
" while (tok && tok->str() != \" ; \" ) \n "
" tok = tok->next(); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'while' is redundant or there is possible null pointer dereference: tok. \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
check ( " void foo(Token &tok) \n "
" { \n "
" for (int i = 0; i < tok.size(); i++ ) \n "
" { \n "
" while (!tok) \n "
" char c = tok.read(); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" for (const Token *tok = tokens; tok; tok = tok->next()) \n "
" { \n "
" while (tok && tok->str() != \" ; \" ) \n "
" tok = tok->next(); \n "
" if( !tok ) break; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" for (const Token *tok = tokens; tok; tok = tok ? tok->next() : NULL) \n "
" { \n "
" while (tok && tok->str() != \" ; \" ) \n "
" tok = tok->next(); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(A*a) \n "
" { \n "
" switch (a->b()) { \n "
" case 1: \n "
" while( a ){ \n "
" a = a->next; \n "
" } \n "
" break; \n "
" case 2: \n "
" a->b(); \n "
" break; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-09 15:09:02 +02:00
// dereference in outer scope..
2014-06-22 10:02:14 +02:00
check ( " void foo(int x, const Token *tok) { \n "
" if (x == 123) { \n "
" while (tok) tok = tok->next(); \n "
" } \n "
" tok->str(); \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:3]: (warning, inconclusive) Possible null pointer dereference: tok - otherwise it is redundant to check it against null. \n " , " " , errout . str ( ) ) ;
2011-10-23 23:36:57 +02:00
check ( " int foo(const Token *tok) \n "
" { \n "
" while (tok){;} \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int foo(const Token *tok) \n "
" { \n "
" while (tok){;} \n "
" char a[2] = {0,0}; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-09 15:09:02 +02:00
}
2014-11-20 14:20:09 +01:00
void nullpointer1 ( ) {
2010-10-31 11:51:25 +01:00
// ticket #1923 - no false positive when using else if
check ( " void f(A *a) \n "
" { \n "
" if (a->x == 1) \n "
" { \n "
" a = a->next; \n "
" } \n "
" else if (a->x == 2) { } \n "
" if (a) { } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ticket #2134 - sizeof doesn't dereference
check ( " void f() { \n "
" int c = 1; \n "
" int *list = NULL; \n "
" sizeof(*list); \n "
" if (!list) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-29 20:19:31 +01:00
// ticket #2245 - sizeof doesn't dereference
check ( " void f(Bar *p) { \n "
" if (!p) { \n "
" int sz = sizeof(p->x); \n "
" } \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-11-29 20:19:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer2 ( ) {
2010-10-31 11:51:25 +01:00
// Null pointer dereference can only happen with pointers
check ( " void foo() \n "
" { \n "
" Fred fred; \n "
" while (fred); \n "
" fred.hello(); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
// Dereferencing a struct and then checking if it is null
// This is checked by this function:
// CheckOther::nullPointerStructByDeRefAndChec
2014-11-20 14:20:09 +01:00
void structDerefAndCheck ( ) {
2010-10-31 11:51:25 +01:00
// errors..
check ( " void foo(struct ABC *abc) \n "
" { \n "
" int a = abc->a; \n "
" if (!abc) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-02-19 21:01:38 +01:00
check ( " void foo(struct ABC *abc) { \n "
2010-10-31 11:51:25 +01:00
" bar(abc->a); \n "
2014-05-22 19:48:00 +02:00
" bar(x, abc->a); \n "
" bar(x, y, abc->a); \n "
2010-10-31 11:51:25 +01:00
" if (!abc) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc. \n "
" [test.cpp:5] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc. \n "
" [test.cpp:5] -> [test.cpp:4]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-02-19 21:01:38 +01:00
2011-02-20 19:45:34 +01:00
check ( " void foo(ABC *abc) { \n "
" if (abc->a == 3) { \n "
" return; \n "
" } \n "
" if (abc) {} \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-02-20 19:45:34 +01:00
2011-08-01 21:57:23 +02:00
check ( " void f(ABC *abc) { \n "
" if (abc->x == 0) { \n "
" return; \n "
" } \n "
" if (!abc); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-08-01 21:57:23 +02:00
2011-02-19 21:01:38 +01:00
// TODO: False negative if member of member is dereferenced
check ( " void foo(ABC *abc) { \n "
" abc->next->a = 0; \n "
" if (abc->next) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2]: (warning) Possible null pointer dereference: abc - otherwise it is redundant to check it against null. \n " , " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-02-19 21:10:31 +01:00
check ( " void foo(ABC *abc) { \n "
" abc->a = 0; \n "
" if (abc && abc->b == 0) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'if(abc&&abc->b==0)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-02-19 21:10:31 +01:00
2010-10-31 11:51:25 +01:00
// ok dereferencing in a condition
check ( " void foo(struct ABC *abc) \n "
" { \n "
" if (abc && abc->a); \n "
" if (!abc) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-02 06:11:55 +01:00
check ( " void f(struct ABC *abc) { \n "
" int x = abc && a(abc->x); \n "
" if (abc) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// ok to use a linked list..
check ( " void foo(struct ABC *abc) \n "
" { \n "
" abc = abc->next; \n "
" if (!abc) \n "
" ; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-08 19:30:14 +01:00
check ( " void f(struct ABC *abc) { \n "
" abc = (ABC *)(abc->_next); \n "
" if (abc) { } "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-12-08 19:30:14 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// reassign struct..
check ( " void foo(struct ABC *abc) \n "
" { \n "
" int a = abc->a; \n "
" abc = abc->next; \n "
" if (!abc) \n "
" ; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(struct ABC *abc) \n "
" { \n "
" int a = abc->a; \n "
" f(&abc); \n "
" if (!abc) \n "
" ; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// goto..
check ( " void foo(struct ABC *abc) \n "
" { \n "
" int a; \n "
" if (!abc) \n "
" goto out; "
" a = abc->a; \n "
" return; \n "
" out: \n "
" if (!abc) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// loops..
check ( " void foo(struct ABC *abc) \n "
" { \n "
" int a = abc->a; "
" do \n "
" { \n "
" if (abc) \n "
" abc = abc->next; \n "
" --a; \n "
" } \n "
" while (a > 0); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) \n "
" { \n "
" while (tok && tok->str() != \" { \" ) \n "
" tok = tok->next(); \n "
" if (!tok) \n "
" return; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// dynamic_cast..
check ( " void foo(ABC *abc) \n "
" { \n "
" int a = abc->a; \n "
" if (!dynamic_cast<DEF *>(abc)) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-12 15:02:06 +01:00
// #2641 - global pointer, function call
check ( " ABC *abc; \n "
" void f() { \n "
" abc->a = 0; \n "
" do_stuff(); \n "
" if (abc) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-12 17:42:58 +01:00
2011-03-12 20:57:19 +01:00
check ( " Fred *fred; \n "
" void f() { \n "
" fred->foo(); \n "
" if (fred) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-12 17:42:58 +01:00
// #2641 - local pointer, function call
check ( " void f() { \n "
2017-04-24 18:27:16 +02:00
" ABC *abc = abc1; \n "
2011-03-12 17:42:58 +01:00
" abc->a = 0; \n "
" do_stuff(); \n "
" if (abc) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-03-12 18:27:19 +01:00
// #2641 - local pointer, function call
check ( " void f(ABC *abc) { \n "
" abc->a = 0; \n "
" do_stuff(); \n "
" if (abc) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-03-28 17:28:21 +02:00
// #2691 - switch/break
check ( " void f(ABC *abc) { \n "
" switch ( x ) { \n "
" case 14: \n "
" sprintf(buf, \" %d \" , abc->a); \n "
" break; \n "
" case 15: \n "
" if ( abc ) {} \n "
" break; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-07 21:08:21 +02:00
// #3128
check ( " void f(ABC *abc) { \n "
" x(!abc || y(abc->a)); \n "
" if (abc) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-30 17:59:38 +01:00
2013-10-22 10:47:48 +02:00
check ( " void f(ABC *abc) { \n "
" x(def || !abc || y(def, abc->a)); \n "
" if (abc) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(ABC *abc) { \n "
" x(abc && y(def, abc->a)); \n "
" if (abc) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(ABC *abc) { \n "
" x(def && abc && y(def, abc->a)); \n "
" if (abc) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-30 17:59:38 +01:00
// #3228 - calling function with null object
{
const char code [ ] = " void f(Fred *fred) { \n "
" fred->x(); \n "
" if (fred) { } \n "
" } " ;
check ( code ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( code , true ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(fred)' is redundant or there is possible null pointer dereference: fred. \n " , errout . str ( ) ) ;
2011-10-30 17:59:38 +01:00
}
2011-12-18 13:33:23 +01:00
2014-01-03 18:53:37 +01:00
// #3425 - false positives when there are macros
2017-05-18 21:52:31 +02:00
checkP ( " #define IF if \n "
" void f(struct FRED *fred) { \n "
" fred->x = 0; \n "
" IF(!fred){} \n "
" } " ) ;
2011-12-18 13:33:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
}
// Dereferencing a pointer and then checking if it is null
2014-11-20 14:20:09 +01:00
void pointerDerefAndCheck ( ) {
2010-10-31 11:51:25 +01:00
// errors..
check ( " void foo(int *p) \n "
" { \n "
" *p = 0; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-08-02 11:20:09 +02:00
check ( " void foo(int *p) \n "
" { \n "
" *p = 0; \n "
" if (p) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-08-02 11:20:09 +02:00
2011-08-02 17:04:07 +02:00
check ( " void foo(int *p) \n "
" { \n "
" *p = 0; \n "
" if (p || q) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p||q)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-08-02 17:04:07 +02:00
2010-10-31 11:51:25 +01:00
check ( " void foo(int *p) \n "
" { \n "
" bar(*p); \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-07-31 14:07:35 +02:00
check ( " void foo(char *p) \n "
" { \n "
" strcpy(p, \" abc \" ); \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-07-31 14:07:35 +02:00
2011-08-02 17:20:13 +02:00
check ( " void foo(char *p) \n "
" { \n "
" if (*p == 0) { } \n "
" if (!p) { } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-08-02 17:20:13 +02:00
2010-10-31 11:51:25 +01:00
// no error
check ( " void foo() \n "
" { \n "
" int *p; \n "
" f(&p); \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int **p = f(); \n "
" if (!p) \n "
" ; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int *p) \n "
" { \n "
" if (x) \n "
" p = 0; \n "
" else \n "
" *p = 0; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int x) \n "
" { \n "
" int a = 2 * x; "
" if (x == 0) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(int *p) \n "
" { \n "
" int var1 = p ? *p : 0; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-02 19:27:18 +02:00
check ( " void foo(int *p) \n "
" { \n "
" int var1 = x ? *p : 5; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-10-02 19:27:18 +02:00
2013-05-03 16:18:44 +02:00
// while
check ( " void f(int *p) { \n "
" *p = 0; \n "
" while (p) { p = 0; } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p) { \n "
" *p = 0; \n "
" while (p) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'while(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2013-05-03 16:18:44 +02:00
2011-10-02 19:27:18 +02:00
// Ticket #3125
check ( " void foo(ABC *p) \n "
" { \n "
" int var1 = p ? (p->a) : 0; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-02 19:27:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo(ABC *p) \n "
" { \n "
" int var1 = p ? (1 + p->a) : 0; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-02 19:27:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-01-21 19:38:59 +01:00
check ( " void f() { \n "
" int * a=0; \n "
" if (!a) {}; \n "
" int c = a ? 0 : 1; \n "
2015-07-25 14:17:55 +02:00
" } \n " , true ) ;
2013-01-21 19:38:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #3686
check ( " void f() { \n "
" int * a=0; \n "
" if (!a) {}; \n "
" int c = a ? b : b+1; \n "
2015-07-25 14:17:55 +02:00
" } \n " , true ) ;
2013-01-21 19:38:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int * a=0; \n "
" if (!a) {}; \n "
" int c = (a) ? b : b+1; \n "
2015-07-25 14:17:55 +02:00
" } \n " , true ) ;
2013-01-21 19:38:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
check ( " void foo(P *p) \n "
" { \n "
" while (p) \n "
" if (p->check()) \n "
" break; \n "
" else \n "
" p = p->next(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 19:48:58 +01:00
check ( " void f(Document *doc) { \n "
" int x = doc && doc->x; \n "
" if (!doc) { \n "
" return; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 18:18:19 +01:00
2011-10-07 21:08:21 +02:00
// #3128 - false positive
check ( " void f(int *p) { \n "
" assert(!p || (*p<=6)); \n "
" if (p) { *p = 0; } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p) { \n "
" assert(p && (*p<=6)); \n "
" if (p) { *p = 0; } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-08 12:58:10 +02:00
check ( " void f(int *p) { \n "
" *p = 12; \n "
" assert(p && (*p<=6)); \n "
" if (p) { *p = 0; } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-10-08 12:58:10 +02:00
2010-11-04 18:18:19 +01:00
check ( " void foo(x *p) \n "
" { \n "
" p = p->next; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-04 18:18:19 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-17 21:09:12 +01:00
check ( " void foo(x *p) \n "
" { \n "
" p = bar(p->next); \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-17 21:09:12 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-08 17:16:52 +01:00
2011-06-21 18:45:30 +02:00
check ( " void foo(x *p) \n "
" { \n "
" p = aa->bar(p->next); \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-06-21 18:45:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-01 07:06:14 +02:00
check ( " void foo(x *p) \n "
" { \n "
" p = *p2 = p->next; \n "
" if (!p) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-01 07:06:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-08 17:16:52 +01:00
check ( " void foo(struct ABC *abc) \n "
" { \n "
" abc = abc ? abc->next : 0; \n "
" if (!abc) \n "
" ; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-08 17:16:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-10 19:57:26 +01:00
2013-01-29 17:12:14 +01:00
check ( " void f(struct ABC *abc) { \n " // #4523
" abc = (*abc).next; \n "
" if (abc) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-01-30 16:52:12 +01:00
check ( " void f(struct ABC *abc) { \n " // #4523
" abc = (*abc->ptr); \n "
" if (abc) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-29 18:45:32 +02:00
check ( " int f(Item *item) { \n "
" x = item ? ab(item->x) : 0; \n "
" if (item) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-29 18:45:32 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(Item *item) { \n "
" item->x = 0; \n "
" a = b ? c : d; \n "
" if (item) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(item)' is redundant or there is possible null pointer dereference: item. \n " , errout . str ( ) ) ;
2011-03-29 18:45:32 +02:00
2011-01-10 19:57:26 +01:00
check ( " BOOL GotoFlyAnchor() \n " // #2243
" { \n "
" const SwFrm* pFrm = GetCurrFrm(); \n "
" do { \n "
" pFrm = pFrm->GetUpper(); \n "
" } while( pFrm && !pFrm->IsFlyFrm() ); \n "
" \n "
" if( !pFrm ) \n "
" return FALSE; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-10 19:57:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-15 12:09:36 +01:00
// Ticket #2463
2012-12-06 19:19:22 +01:00
check ( " struct A \n "
2011-01-15 12:09:36 +01:00
" { \n "
" B* W; \n "
" \n "
" void f() { \n "
" switch (InData) { \n "
" case 2: \n "
" if (!W) return; \n "
" W->foo(); \n "
" break; \n "
" case 3: \n "
" f(); \n "
" if (!W) return; \n "
" break; \n "
" } \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-15 12:09:36 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-31 17:30:27 +01:00
// #2525 - sizeof
check ( " void f() { \n "
" int *test = NULL; \n "
" int c = sizeof(test[0]); \n "
" if (!test) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-01-31 17:30:27 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-20 09:47:55 +02:00
2013-11-02 23:56:10 +01:00
check ( " void f(type* p) { \n " // #4983
" x(sizeof p[0]); \n "
" if (!p) \n "
" ; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2013-11-02 23:56:10 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-20 09:47:55 +02:00
// #3023 - checked deref
check ( " void f(struct ABC *abc) { \n "
" WARN_ON(!abc || abc->x == 0); \n "
" if (!abc) { } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-08-20 09:47:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(struct ABC *abc) { \n "
" WARN_ON(!abc || abc->x == 7); \n "
" if (!abc) { } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-08-20 09:47:55 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-18 13:33:23 +01:00
2014-01-03 18:53:37 +01:00
// #3425 - false positives when there are macros
2017-05-18 21:52:31 +02:00
checkP ( " #define IF if \n "
" void f(int *p) { \n "
" *p = 0; \n "
" IF(!p){} \n "
" } " ) ;
2011-12-18 13:33:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-07-23 10:05:55 +02:00
check ( " void f() { \n " // #3914 - false positive
" int *p; \n "
" ((p=ret()) && (x=*p)); \n "
" if (p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer5 ( ) {
2010-10-31 11:51:25 +01:00
// errors..
check ( " void foo(A &a) \n "
" { \n "
" char c = a.c(); \n "
" if (!a) \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
// Execution paths..
2014-11-20 14:20:09 +01:00
void nullpointerExecutionPaths ( ) {
2010-10-31 11:51:25 +01:00
// errors..
check ( " static void foo() \n "
" { \n "
" Foo *p = 0; \n "
2013-04-15 19:00:15 +02:00
" if (a == 1) { \n "
2010-10-31 11:51:25 +01:00
" p = new FooBar; \n "
2013-04-15 19:00:15 +02:00
" } else { if (a == 2) { \n "
" p = new FooCar; } } \n "
2010-10-31 11:51:25 +01:00
" p->abcd(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:8]: (error) Possible null pointer dereference: p \n " ,
" " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2013-04-15 19:00:15 +02:00
check ( " static void foo() { \n "
" int &r = *0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2013-04-15 19:00:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2013-04-15 19:00:15 +02:00
check ( " static void foo(int x) { \n "
" int y = 5 + *0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2013-04-15 19:00:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2011-10-18 19:34:14 +02:00
{
2014-01-22 20:16:31 +01:00
const char code [ ] = " static void foo() { \n "
2011-10-18 19:34:14 +02:00
" Foo<int> *abc = 0; \n "
" abc->a(); \n "
" } \n " ;
// inconclusive=false => no error
check ( code , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// inconclusive=true => error
check ( code , true ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error, inconclusive) Null pointer dereference: abc \n " , errout . str ( ) ) ;
2011-10-18 19:34:14 +02:00
}
2010-10-31 11:51:25 +01:00
2013-04-15 19:00:15 +02:00
check ( " static void foo() { \n "
" std::cout << *0; "
2013-03-20 15:36:16 +01:00
" } " ) ;
2013-04-15 19:00:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
check ( " void f() \n "
" { \n "
" char *c = 0; \n "
" { \n "
" delete c; \n "
" } \n "
" c[0] = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Null pointer dereference: c \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2013-04-15 19:00:15 +02:00
check ( " static void foo() { \n "
" if (3 > *0); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2013-04-15 19:00:15 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// no false positive..
check ( " static void foo() \n "
" { \n "
" Foo *p = 0; \n "
" p = new Foo; \n "
" p->abcd(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int sz = sizeof((*(struct dummy *)0).x); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void get_offset(long &offset) \n "
" { \n "
" mystruct * temp; temp = 0; \n "
" offset = (long)(&(temp->z)); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Ticket #1893 - try/catch inside else
check ( " int *test(int *Z) \n "
" { \n "
" int *Q=NULL; \n "
" if (Z) { \n "
" Q = Z; \n "
" } \n "
" else { \n "
" Z = new int; \n "
" try { \n "
" } catch(...) { \n "
" } \n "
" Q = Z; \n "
" } \n "
" *Q=1; \n "
" return Q; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int *test(int *Z) \n "
" { \n "
" int *Q=NULL; \n "
" if (Z) { \n "
" Q = Z; \n "
" } \n "
" else { \n "
" try { \n "
" } catch(...) { \n "
" } \n "
" } \n "
" *Q=1; \n "
" return Q; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (warning) Possible null pointer dereference: Q \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// Ticket #2052 (false positive for 'else continue;')
check ( " void f() { \n "
" for (int x = 0; x < 5; ++x) { "
" int *p = 0; \n "
" if (a(x)) p=b(x); \n "
" else continue; \n "
" *p = 0; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// function pointer..
check ( " void foo() \n "
" { \n "
" void (*f)(); \n "
" f = 0; \n "
" f(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Null pointer dereference: f \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// loops..
check ( " void f() { \n "
" int *p = 0; \n "
" for (int i = 0; i < 10; ++i) { \n "
" int x = *p + 1; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
check ( " void f(int a) { \n "
" const char *p = 0; \n "
" if (a) { \n "
2011-02-05 12:53:28 +01:00
" p = \" abcd \" ; \n "
2010-10-31 11:51:25 +01:00
" } \n "
" for (int i = 0; i < 3; i++) { \n "
" if (a && (p[i] == '1')); \n "
" } \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-29 20:30:23 +01:00
// ticket #2251: taking the address of member
check ( " void f() { \n "
" Fred *fred = 0; \n "
" int x = &fred->x; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-11-29 20:30:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-18 19:34:14 +02:00
// ticket #3220: calling member function
check ( " void f() { \n "
" Fred *fred = NULL; \n "
" fred->do_something(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-02-01 20:38:47 +01:00
// ticket #3570 - parsing of conditions
{
check ( " void f() { \n "
" int *p = NULL; \n "
" if (x) \n "
" p = q; \n "
" if (p && *p) { } \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-02-01 20:38:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int *p = NULL; \n "
" if (x) \n "
" p = q; \n "
" if (!p || *p) { } \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-02-01 20:38:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int *p = NULL; \n "
" if (x) \n "
" p = q; \n "
" if (p || *p) { } \n "
" } " ) ;
2015-07-29 19:54:57 +02:00
ASSERT_EQUALS ( " [test.cpp:5] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2012-02-01 20:38:47 +01:00
}
2019-02-26 17:14:45 +01:00
// ticket #8831 - FP triggered by if/return/else sequence
{
check ( " void f(int *p, int *q) { \n "
" if (p == NULL) \n "
" return; \n "
" else if (q == NULL) \n "
" return; \n "
" *q = 0; \n "
" } \n "
" \n "
" void g() { \n "
" f(NULL, NULL); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-31 11:51:25 +01:00
}
2010-12-26 13:38:16 +01:00
// Ticket #2350
2014-11-20 14:20:09 +01:00
void nullpointerExecutionPathsLoop ( ) {
2010-12-26 13:38:16 +01:00
// No false positive:
check ( " void foo() { \n "
" int n; \n "
2014-01-22 20:16:31 +01:00
" int *argv32 = p; \n "
2010-12-26 13:38:16 +01:00
" if (x) { \n "
" n = 0; \n "
" argv32 = 0; \n "
" } \n "
" \n "
" for (int i = 0; i < n; i++) { \n "
" argv32[i] = 0; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-26 13:38:16 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// No false negative:
check ( " void foo() { \n "
" int n; \n "
" int *argv32; \n "
" if (x) { \n "
" n = 10; \n "
" argv32 = 0; \n "
" } \n "
" \n "
" for (int i = 0; i < n; i++) { \n "
" argv32[i] = 0; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " error " ,
" " , errout . str ( ) ) ;
2011-02-19 20:19:46 +01:00
// #2231 - error if assignment in loop is not used
check ( " void f() { \n "
" char *p = 0; \n "
" \n "
" for (int x = 0; x < 3; ++x) { \n "
" if (y[x] == 0) { \n "
" p = malloc(10); \n "
" break; \n "
" } \n "
" } \n "
" \n "
" *p = 0; \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (warning) Possible null pointer dereference: p \n " , errout . str ( ) ) ;
2010-12-26 13:38:16 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer7 ( ) {
2010-10-31 11:51:25 +01:00
check ( " void foo() \n "
" { \n "
" wxLongLong x = 0; \n "
" int y = x.GetValue(); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer9 ( ) { //#ticket 1778
2010-10-31 11:51:25 +01:00
check ( " void foo() \n "
" { \n "
" std::string * x = 0; \n "
" *x = \" test \" ; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: x \n " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer10 ( ) {
2011-05-28 05:30:19 +02:00
check ( " void foo() \n "
" { \n "
" struct my_type* p = 0; \n "
" p->x = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2011-06-04 04:16:08 +02:00
}
2014-11-20 14:20:09 +01:00
void nullpointer11 ( ) { // ticket #2812
2011-05-28 05:30:19 +02:00
check ( " int foo() \n "
" { \n "
" struct my_type* p; \n "
2012-12-06 19:19:22 +01:00
" p = 0; \n "
2011-05-28 05:30:19 +02:00
" return p->x; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2011-05-28 05:30:19 +02:00
}
2014-11-20 14:20:09 +01:00
void nullpointer12 ( ) { // ticket #2470, #4035
2012-08-25 12:00:25 +02:00
const char code [ ] = " int foo() \n "
" { \n "
" int* i = nullptr; \n "
" return *i; \n "
" } \n " ;
2015-07-25 14:17:55 +02:00
check ( code , false , " test.cpp " ) ; // C++ file => nullptr means NULL
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: i \n " , errout . str ( ) ) ;
2011-10-16 12:54:58 +02:00
2015-07-25 14:17:55 +02:00
check ( code , false , " test.c " ) ; // C file => nullptr does not mean NULL
2011-10-16 12:54:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer15 ( ) { // #3560
2012-01-28 08:06:03 +01:00
check ( " void f() { \n "
" char *p = 0; \n "
" if (x) p = \" abcd \" ; \n "
" return p ? f(*p) : f(0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer16 ( ) { // #3591
2012-02-13 19:46:45 +01:00
check ( " void foo() { \n "
" int *p = 0; \n "
" bar(&p); \n "
" *p = 0; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-02-13 19:46:45 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer17 ( ) { // #3567
2012-03-07 20:31:23 +01:00
check ( " int foo() { \n "
" int *p = 0; \n "
2013-04-15 19:00:15 +02:00
" if (x) { return 0; } \n "
" return !p || *p; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-03-07 20:31:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int foo() { \n "
" int *p = 0; \n "
2013-04-15 19:00:15 +02:00
" if (x) { return 0; } \n "
2012-03-07 20:31:23 +01:00
" return p && *p; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-03-07 20:31:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer18 ( ) { // #1927
2012-04-01 15:54:41 +02:00
check ( " void f () \n "
" { \n "
" int i=0; \n "
2012-04-01 15:56:48 +02:00
" char *str=NULL; \n "
" while (str[i]) \n "
" { \n "
" i++; \n "
" }; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Null pointer dereference: str \n " , errout . str ( ) ) ;
2012-04-01 15:54:41 +02:00
}
2014-11-20 14:20:09 +01:00
void nullpointer19 ( ) { // #3811
2012-05-16 09:56:39 +02:00
check ( " int foo() { \n "
" perror(0); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer20 ( ) { // #3807
2012-05-31 18:41:00 +02:00
check ( " void f(int x) { \n "
" struct xy *p = 0; \n "
" if (x) p = q; \n "
" if (p ? p->x || p->y : 0) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n " // false negative
" struct xy *p = 0; \n "
" if (x) p = q; \n "
" if (y ? p->x : p->y) { } \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Possible null pointer dereference: p \n " , errout . str ( ) ) ;
2012-05-31 18:41:00 +02:00
}
2014-11-20 14:20:09 +01:00
void nullpointer21 ( ) { // #4038 - fp: if (x) p=q; else return;
2012-09-23 09:20:16 +02:00
check ( " void f(int x) { \n "
" int *p = 0; \n "
" if (x) p = q; \n "
" else return; \n "
" *p = 0; \n " // <- p is not NULL
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer23 ( ) { // #4665
2013-03-19 08:47:05 +01:00
check ( " void f(){ \n "
" char *c = NULL; \n "
" char cBuf[10]; \n "
" sprintf(cBuf, \" %s \" , c ? c : \" 0 \" ); \n "
" } " ) ;
2013-11-04 23:09:15 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-03-19 08:47:05 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer24 ( ) { // #5083 - fp: chained assignment
2013-10-20 13:37:36 +02:00
check ( " void f(){ \n "
" char *c = NULL; \n "
" x = c = new char[10]; \n "
" *c = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer25 ( ) { // #5061
2014-03-26 12:17:27 +01:00
check ( " void f(int *data, int i) \n "
" { \n "
" int *array = NULL; \n "
" if (data == 1 && array[i] == 0) \n "
" std::cout << \" test \" ; \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: array \n " , errout . str ( ) ) ;
2014-03-26 12:17:27 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer26 ( ) { // #3589
2014-03-27 19:16:30 +01:00
check ( " double foo() { \n "
" sk *t1 = foo(); \n "
" sk *t2 = foo(); \n "
" if ((!t1) && (!t2)) \n "
" return 0.0; \n "
" if (t1 && (!t2)) \n "
" return t1->Inter(); \n "
" if (t2->GetT() == t) \n "
" return t2->Inter(); \n "
" if (t2 && (!t1)) \n "
" return 0.0; \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-05-16 21:11:04 +02:00
void nullpointer27 ( ) { // #6568
check ( " template<class Type> \n "
" class Foo { \n "
" Foo<Type>& operator = ( Type* ); \n "
" }; \n "
" template<class Type> \n "
" Foo<Type>& Foo<Type>::operator = ( Type* pointer_ ) { \n "
" pointer_=NULL; \n "
" *pointer_=0; \n "
" return *this; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:8]: (error) Null pointer dereference: pointer_ \n " , errout . str ( ) ) ;
}
2015-08-15 00:31:26 +02:00
void nullpointer28 ( ) { // #6491
check ( " typedef struct { int value; } S; \n "
" int f(const S *s) { \n "
" int i = s ? s->value + 1 \n "
" : s->value - 1; // <-- null ptr dereference \n "
" return i; \n "
2018-12-18 14:36:49 +01:00
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (warning) Possible null pointer dereference: s \n " , " " , errout . str ( ) ) ;
2015-08-15 00:31:26 +02:00
}
2015-08-15 01:00:36 +02:00
void nullpointer30 ( ) { // #6392
check ( " void f(std::vector<std::string> *values) \n "
" { \n "
" values->clear(); \n "
" if (values) \n "
" { \n "
" for (int i = 0; i < values->size(); ++i) \n "
" { \n "
" values->push_back( \" test \" ); \n "
" } \n "
" } \n "
" } \n " , true ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'if(values)' is redundant or there is possible null pointer dereference: values. \n " , errout . str ( ) ) ;
2015-08-15 01:00:36 +02:00
}
2018-04-09 16:13:17 +02:00
void nullpointer31 ( ) { // #8482
check ( " struct F \n "
" { \n "
" int x; \n "
" }; \n "
" \n "
" static void foo(F* f) \n "
" { \n "
" if( f ) {} \n "
" else { return; } \n "
" (void)f->x; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-11-03 15:53:24 +01:00
void nullpointer32 ( ) { // #8460
check ( " int f(int * ptr) { \n "
" if(ptr) \n "
" { return 0;} \n "
" else{ \n "
" int *p1 = ptr; \n "
" return *p1; \n "
" } \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:6]: (warning) Either the condition 'ptr' is redundant or there is possible null pointer dereference: p1. \n " , errout . str ( ) ) ;
}
2015-01-05 14:54:24 +01:00
void nullpointer_addressOf ( ) { // address of
check ( " void f() { \n "
" struct X *x = 0; \n "
" if (addr == &x->y) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" struct X *x = 0; \n "
" if (addr == &x->y.z[0]) {} \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointerSwitch ( ) { // #2626
2014-03-28 10:06:24 +01:00
check ( " char *f(int x) { \n "
" char *p = do_something(); \n "
" switch (x) { \n "
" case 1: \n "
" p = 0; \n "
" case 2: \n "
" *p = 0; \n "
" break; \n "
" } \n "
" return p; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2019-03-16 09:17:50 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (warning) Possible null pointer dereference: p \n " , errout . str ( ) ) ;
2014-03-28 10:06:24 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer_cast ( ) { // #4692
2013-04-03 10:27:08 +02:00
check ( " char *nasm_skip_spaces(const char *p) { \n "
" if (p) \n "
" while (*p && nasm_isspace(*p)) \n "
" p++; \n "
2013-04-15 19:00:15 +02:00
" return p; \n "
2013-04-03 10:27:08 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void nullpointer_castToVoid ( ) { // #3771
2012-04-30 12:36:41 +02:00
check ( " void f () { \n "
2013-04-15 19:00:15 +02:00
" int *buf; buf = NULL; \n "
" buf; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-10-31 11:51:25 +01:00
// Check if pointer is null and the dereference it
2014-11-20 14:20:09 +01:00
void pointerCheckAndDeRef ( ) {
2010-10-31 11:51:25 +01:00
check ( " void foo(char *p) { \n "
" if (!p) { \n "
" } \n "
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2010-11-12 19:42:02 +01:00
2011-02-19 21:28:18 +01:00
check ( " void foo(char *p) { \n "
" if (p && *p == 0) { \n "
" } \n "
" printf( \" %c \" , *p); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-02-19 21:28:18 +01:00
2011-02-20 14:38:49 +01:00
check ( " void foo(char *p) { \n "
" if (p && *p == 0) { \n "
" } else { *p = 0; } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-02-20 14:38:49 +01:00
2011-07-31 17:19:23 +02:00
check ( " void foo(char *p) { \n "
" if (p) { \n "
" } \n "
" strcpy(p, \" abc \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-07-31 17:19:23 +02:00
2011-07-31 17:32:25 +02:00
check ( " void foo(char *p) { \n "
" if (p) { \n "
" } \n "
" bar(); \n "
" strcpy(p, \" abc \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-07-31 17:32:25 +02:00
2010-10-31 11:51:25 +01:00
check ( " void foo(abc *p) { \n "
" if (!p) { \n "
" } \n "
2013-04-15 19:00:15 +02:00
" else { if (!p->x) { \n "
" } } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-04-13 10:49:17 +02:00
{
static const char code [ ] =
" void foo(char *p) { \n "
" if (!p) { \n "
" abort(); \n "
" } \n "
" *p = 0; \n "
" } " ;
check ( code , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
2013-04-13 10:49:17 +02:00
check ( code , true ) ;
2014-03-21 17:36:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-04-13 10:49:17 +02:00
}
2011-10-29 10:35:31 +02:00
check ( " void foo(char *p) { \n "
" if (!p) { \n "
2011-01-05 21:48:26 +01:00
" (*bail)(); \n "
" } \n "
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-05 21:48:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
check ( " void foo(char *p) { \n "
" if (!p) { \n "
" throw x; \n "
" } \n "
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-09-03 19:43:27 +02:00
check ( " void foo(char *p) { \n "
" if (!p) { \n "
" ab.abort(); \n "
" } \n "
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-09-03 19:43:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 21:09:32 +01:00
check ( " void foo(char *p) { \n "
2010-10-31 11:51:25 +01:00
" if (!p) { \n "
" switch (x) { } \n "
" } \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-04 21:09:32 +01:00
check ( " void foo(char *p) { \n "
2010-11-01 19:21:08 +01:00
" if (!p) { \n "
" } \n "
" return *x; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2010-11-01 19:21:08 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-01-25 15:16:22 +01:00
check ( " int foo(int *p) { \n "
" if (!p) { \n "
" x = *p; \n "
" return 5+*p; \n "
" } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n "
" [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2012-01-25 15:16:22 +01:00
2010-11-04 21:09:32 +01:00
// operator!
check ( " void f() { \n "
" A a; \n "
" if (!a) { \n "
" a.x(); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-04 21:09:32 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
// This is why this check can't be used on the simplified token list
check ( " void f(Foo *foo) { \n "
" if (!dynamic_cast<bar *>(foo)) { \n "
" *foo = 0; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2010-10-31 11:51:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-16 21:41:50 +01:00
// ticket: #2300 - calling unknown function that may initialize the pointer
check ( " Fred *fred; \n "
" void a() { \n "
" if (!fred) { \n "
" initfred(); \n "
" fred->x = 0; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-16 21:41:50 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-09 20:16:16 +01:00
// ticket #1219
check ( " void foo(char *p) { \n "
" if (p) { \n "
" return; \n "
" } \n "
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-01-17 19:23:00 +01:00
// #2467 - unknown macro may terminate the application
check ( " void f(Fred *fred) { \n "
" if (fred == NULL) { \n "
" MACRO; \n "
" } \n "
" fred->a(); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-01-17 19:23:00 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-23 08:38:09 +01:00
// #2493 - switch
check ( " void f(Fred *fred) { \n "
" if (fred == NULL) { \n "
" x = 0; \n "
" } \n "
" switch (x) { \n "
" case 1: \n "
" fred->a(); \n "
" break; \n "
" }; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-01-23 08:38:09 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-02-18 20:05:44 +01:00
2012-09-18 19:16:28 +02:00
// #4118 - second if
check ( " void f(char *p) { \n "
" int x = 1; \n "
" if (!p) x = 0; \n "
" if (x) *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-27 11:04:58 +02:00
// #2674 - different functions
check ( " class Fred { \n "
" public: \n "
" Wilma *wilma; \n "
" void a(); \n "
" void b(); \n "
" }; \n "
" \n "
" void Fred::a() { \n "
" if ( wilma ) { } \n "
" } \n "
" \n "
" void Fred::b() { \n "
" wilma->Reload(); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-03-27 11:04:58 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-27 21:29:49 +02:00
check ( " void test(int *i) { \n "
2013-04-15 19:00:15 +02:00
" if(i == NULL) { } \n "
" else { \n "
2011-03-27 21:29:49 +02:00
" int b = *i; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-03-27 21:29:49 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-04-03 21:06:42 +02:00
// #2696 - false positives nr 1
check ( " void f() \n "
" { \n "
" struct foo *pFoo = NULL; \n "
" size_t len; \n "
" \n "
" len = sizeof(*pFoo) - sizeof(pFoo->data); \n "
" \n "
" if (pFoo) \n "
" bar(); \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-04-03 21:06:42 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #2696 - false positives nr 2
check ( " void f() \n "
" { \n "
" struct foo *pFoo = NULL; \n "
" size_t len; \n "
" \n "
" while (pFoo) \n "
" pFoo = pFoo->next; \n "
" \n "
" len = sizeof(pFoo->data); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-04-03 21:06:42 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #2696 - false positives nr 3
check ( " void f() \n "
" { \n "
" struct foo *pFoo = NULL; \n "
" size_t len; \n "
" \n "
" while (pFoo) \n "
" pFoo = pFoo->next; \n "
" \n "
" len = decltype(*pFoo); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-04-03 21:06:42 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-07-25 21:58:00 +02:00
check ( " int foo(struct Fred *fred) { \n "
2013-04-15 19:00:15 +02:00
" if (fred) { } \n "
2011-07-25 21:58:00 +02:00
" return fred->a; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'fred' is redundant or there is possible null pointer dereference: fred. \n " , errout . str ( ) ) ;
2011-08-01 07:51:32 +02:00
// #2789 - assign and check pointer
check ( " void f() { \n "
2013-04-15 19:00:15 +02:00
" char *p; p = x(); \n "
" if (!p) { } \n "
2011-08-01 07:51:32 +02:00
" *p = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-08-07 17:06:25 +02:00
// check, assign and use
check ( " void f() { \n "
" char *p; \n "
" if (p == 0 && (p = malloc(10)) != 0) { \n "
" *p = 0; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-08-07 17:06:25 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-29 15:48:54 +02:00
2012-02-11 16:15:38 +01:00
// check, assign and use
check ( " void f() { \n "
" char *p; \n "
" if (p == 0 && (p = malloc(10)) != a && (*p = a)) { \n "
" *p = 0; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-02-11 16:15:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// check, and use
check ( " void f() { \n "
" char *p; \n "
" if (p == 0 && (*p = 0)) { \n "
" return; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-07-29 19:54:57 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2012-02-11 16:15:38 +01:00
// check, and use
check ( " void f() { \n "
" struct foo *p; \n "
" if (p == 0 && p->x == 10) { \n "
" return; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-07-29 19:54:57 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2012-02-11 16:15:38 +01:00
// check, and use
check ( " void f() { \n "
" struct foo *p; \n "
" if (p == 0 || p->x == 10) { \n "
" return; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-02-11 16:15:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// check, and use
check ( " void f() { \n "
2013-04-15 19:00:15 +02:00
" char *p; p = malloc(10); \n "
" if (p == NULL && (*p = a)) { \n "
2012-02-11 16:15:38 +01:00
" return; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2016-10-18 21:44:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==NULL' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2012-02-11 16:15:38 +01:00
// check, and use
check ( " void f(struct X *p, int x) { \n "
" if (!p && x==1 || p && p->x==0) { \n "
" return; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-02-11 16:15:38 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-29 15:48:54 +02:00
{
const char code [ ] = " void f(Fred *fred) { \n "
" if (fred == NULL) { } \n "
" fred->x(); \n "
" } " ;
2015-07-25 14:17:55 +02:00
check ( code , false ) ; // non-inconclusive
2011-10-29 15:48:54 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-25 14:17:55 +02:00
check ( code , true ) ; // inconclusive
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred. \n " , errout . str ( ) ) ;
2011-10-29 15:48:54 +02:00
}
2011-12-03 13:10:07 +01:00
check ( " void f(char *s) { \n " // #3358
" if (s==0); \n "
" strcpy(a, s?b:c); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-12-03 13:10:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-17 12:44:11 +01:00
// sizeof
check ( " void f(struct fred_t *fred) { \n "
" if (!fred) \n "
2013-04-15 19:00:15 +02:00
" int sz = sizeof(fred->x); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-12-17 12:44:11 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-18 13:33:23 +01:00
// check in macro
check ( " void f(int *x) { \n "
" $if (!x) {} \n "
" *x = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-12-25 14:23:50 +01:00
// return ?:
check ( " int f(ABC *p) { \n " // FP : return ?:
" if (!p) {} \n "
" return p ? p->x : 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(ABC *p) { \n " // no fn
" if (!p) {} \n "
" return q ? p->x : 0; \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2014-04-02 19:39:42 +02:00
check ( " int f(ABC *p) { \n " // FP : return &&
" if (!p) {} \n "
" return p && p->x; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-09-02 12:03:05 +02:00
check ( " void f(int x, int *p) { \n "
" if (x || !p) {} \n "
" *p = 0; \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2015-04-20 13:46:02 +02:00
// sizeof
check ( " void f() { \n "
" int *pointer = NULL; \n "
" pointer = func(sizeof pointer[0]); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2015-04-20 13:46:02 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-10-31 11:51:25 +01:00
}
2010-12-26 19:29:58 +01:00
// Test CheckNullPointer::nullConstantDereference
2014-11-20 14:20:09 +01:00
void nullConstantDereference ( ) {
2012-01-25 15:16:22 +01:00
check ( " void f() { \n "
" int* p = 0; \n "
" return p[4]; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2013-06-07 06:37:53 +02:00
2013-10-12 15:19:15 +02:00
check ( " void f() { \n "
" typeof(*NULL) y; \n "
" } " , true ) ;
2013-11-08 13:22:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-26 19:29:58 +01:00
}
2014-11-20 14:20:09 +01:00
void gcc_statement_expression ( ) {
2011-03-13 10:34:54 +01:00
// Ticket #2621
check ( " void f(struct ABC *abc) { \n "
" ({ if (abc) dbg(); }) \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-06-26 21:46:33 +02:00
2014-11-20 14:20:09 +01:00
void snprintf_with_zero_size ( ) {
2011-06-26 21:46:33 +02:00
// Ticket #2840
check ( " void f() { \n "
" int bytes = snprintf(0, 0, \" %u \" , 1); \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-06-26 21:46:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void snprintf_with_non_zero_size ( ) {
2011-06-26 21:46:33 +02:00
// Ticket #2840
check ( " void f() { \n "
" int bytes = snprintf(0, 10, \" %u \" , 1); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
}
2011-10-12 22:11:27 +02:00
2014-11-20 14:20:09 +01:00
void printf_with_invalid_va_argument ( ) {
2011-10-12 22:11:27 +02:00
check ( " void f() { \n "
" printf( \" %s \" , 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f(char* s) { \n "
" printf( \" %s \" , s); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char* s = 0; \n "
" printf( \" %s \" , s); \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference: s \n " , errout . str ( ) ) ;
2011-10-12 22:11:27 +02:00
2011-12-03 13:10:07 +01:00
check ( " void f() { \n "
" char *s = 0; \n "
" printf( \" %s \" , s == 0 ? a : s); \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2011-12-03 13:10:07 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-12 22:11:27 +02:00
check ( " void f() { \n "
" printf( \" %u%s \" , 0, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f(char* s) { \n "
" printf( \" %u%s \" , 0, s); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char* s = 0; \n "
" printf( \" %u%s \" , 123, s); \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference: s \n " , errout . str ( ) ) ;
2011-10-12 22:11:27 +02:00
check ( " void f() { \n "
" printf( \" %%%s%% \" , 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f(char* s) { \n "
" printf( \" text: %s, %s \" , s, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char* s = \" blabla \" ; \n "
" printf( \" %s \" , s); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-28 21:32:07 +01:00
check ( " void f(char* s) { \n "
" printf( \" text: %m%s, %s \" , s, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f(char* s) { \n "
" printf( \" text: %*s, %s \" , s, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2011-11-30 20:23:29 +01:00
// Ticket #3364
check ( " void f() { \n "
" printf( \" %-*.*s \" , s, 0); \n "
" sprintf( \" %* \" , s); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-10-12 22:11:27 +02:00
}
2014-11-20 14:20:09 +01:00
void scanf_with_invalid_va_argument ( ) {
2011-10-12 22:11:27 +02:00
check ( " void f(char* s) { \n "
" sscanf(s, \" %s \" , 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" scanf( \" %d \" , 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2011-10-16 07:06:18 +02:00
check ( " void f(char* foo) { \n "
" char location[200]; \n "
" int width, height; \n "
" sscanf(imgInfo, \" %s %d %d \" , location, &width, &height); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // ticket #3207
check ( " void f(char *dummy) { \n "
" int iVal; \n "
" sscanf(dummy, \" %d%c \" , &iVal); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ; // ticket #3211
check ( " void f(char *dummy) { \n "
" int* iVal = 0; \n "
" sscanf(dummy, \" %d \" , iVal); \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference: iVal \n " , errout . str ( ) ) ;
2011-10-16 07:06:18 +02:00
check ( " void f(char *dummy) { \n "
" int* iVal; \n "
" sscanf(dummy, \" %d \" , foo(iVal)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *dummy) { \n "
" int* iVal = 0; \n "
" sscanf(dummy, \" %d%d \" , foo(iVal), iVal); \n "
" } " ) ;
2014-01-22 20:16:31 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-02 17:09:32 +01:00
check ( " void f(char* dummy) { \n "
" sscanf(dummy, \" %*d%u \" , 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2011-10-12 22:11:27 +02:00
}
2011-10-23 23:36:57 +02:00
2014-11-20 14:20:09 +01:00
void nullpointer_in_return ( ) {
2011-10-23 23:36:57 +02:00
check ( " int foo() { \n "
" int* iVal = 0; \n "
" if(g()) iVal = g(); \n "
" return iVal[0]; \n "
" } " ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (warning) Possible null pointer dereference: iVal \n " , errout . str ( ) ) ;
2011-10-23 23:36:57 +02:00
check ( " int foo(int* iVal) { \n "
" return iVal[0]; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2011-10-23 23:36:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-11-04 09:49:49 +01:00
2014-11-20 14:20:09 +01:00
void nullpointer_in_typeid ( ) {
2011-11-04 09:49:49 +01:00
// Should throw std::bad_typeid
check ( " struct PolymorphicA { virtual ~A() {} }; \n "
" bool foo() { \n "
" PolymorphicA* a = 0; \n "
" return typeid(*a) == typeid(*a); \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-11-11 09:58:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-04 09:49:49 +01:00
check ( " struct NonPolymorphicA { ~A() {} }; \n "
" bool foo() { \n "
" NonPolymorphicA* a = 0; \n "
" return typeid(*a) == typeid(*a); \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-11-11 09:58:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-04 09:49:49 +01:00
check ( " bool foo() { \n "
" char* c = 0; \n "
" return typeid(*c) == typeid(*c); \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2011-11-11 09:58:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-04 09:49:49 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer_in_for_loop ( ) {
2011-11-07 21:10:21 +01:00
// Ticket #3278
check ( " void f(int* ptr, int cnt){ \n "
" if (!ptr) \n "
" cnt = 0; \n "
" for (int i = 0; i < cnt; ++i) \n "
" *ptr++ = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-11-13 22:35:13 +01:00
2014-11-20 14:20:09 +01:00
void nullpointerDelete ( ) {
2011-11-13 22:35:13 +01:00
check ( " void f() { \n "
" K *k = getK(); \n "
" if (k) \n "
" k->doStuff(); \n "
" delete k; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" K *k = getK(); \n "
" if (k) \n "
" k[0] = ptr; \n "
" delete [] k; \n "
" k = new K[10]; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-11-23 21:19:54 +01:00
2014-11-20 14:20:09 +01:00
void nullpointerExit ( ) {
2011-11-23 21:19:54 +01:00
check ( " void f() { \n "
" K *k = getK(); \n "
" if (!k) \n "
" exit(1); \n "
" k->f(); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-12-25 17:01:45 +01:00
2014-11-20 14:20:09 +01:00
void nullpointerStdString ( ) {
2012-01-25 15:16:22 +01:00
check ( " void f(std::string s1) { \n "
" void* p = 0; \n "
" s1 = 0; \n "
2014-09-26 20:40:44 +02:00
" s1 = ' \\ 0'; \n "
2012-01-25 15:16:22 +01:00
" std::string s2 = 0; \n "
2014-09-26 20:40:44 +02:00
" std::string s2 = ' \\ 0'; \n "
2012-01-25 15:16:22 +01:00
" std::string s3(0); \n "
" foo(std::string(0)); \n "
" s1 = p; \n "
" std::string s4 = p; \n "
" std::string s5(p); \n "
" foo(std::string(p)); \n "
" } " , true ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Null pointer dereference: p \n "
" [test.cpp:10]: (error) Null pointer dereference: p \n "
2018-12-29 09:26:57 +01:00
" [test.cpp:11]: (error) Null pointer dereference: p \n "
" [test.cpp:12]: (warning, inconclusive) Possible null pointer dereference: p \n "
2014-10-16 19:12:02 +02:00
" [test.cpp:3]: (error) Null pointer dereference \n "
" [test.cpp:5]: (error) Null pointer dereference \n "
2014-09-26 20:40:44 +02:00
" [test.cpp:7]: (error) Null pointer dereference \n "
" [test.cpp:8]: (error) Null pointer dereference \n "
2014-01-22 20:16:31 +01:00
, errout . str ( ) ) ;
2012-01-25 15:16:22 +01:00
2017-02-24 19:44:28 +01:00
check ( " void f(std::string s1) { \n "
" s1 = nullptr; \n "
" std::string s2 = nullptr; \n "
" std::string s3(nullptr); \n "
" foo(std::string(nullptr)); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n "
" [test.cpp:3]: (error) Null pointer dereference \n "
" [test.cpp:4]: (error) Null pointer dereference \n "
" [test.cpp:5]: (error) Null pointer dereference \n "
, errout . str ( ) ) ;
check ( " void f(std::string s1) { \n "
" s1 = NULL; \n "
" std::string s2 = NULL; \n "
" std::string s3(NULL); \n "
" foo(std::string(NULL)); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Null pointer dereference \n "
" [test.cpp:3]: (error) Null pointer dereference \n "
" [test.cpp:4]: (error) Null pointer dereference \n "
" [test.cpp:5]: (error) Null pointer dereference \n "
, errout . str ( ) ) ;
2012-01-25 15:16:22 +01:00
check ( " void f(std::string s1, const std::string& s2, const std::string* s3) { \n "
" void* p = 0; \n "
2013-04-15 19:00:15 +02:00
" if (x) { return; } \n "
2012-01-25 15:16:22 +01:00
" foo(s1 == p); \n "
" foo(s2 == p); \n "
" foo(s3 == p); \n "
" foo(p == s1); \n "
" foo(p == s2); \n "
" foo(p == s3); \n "
" } " , true ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n "
" [test.cpp:5]: (error) Null pointer dereference: p \n "
" [test.cpp:7]: (error) Null pointer dereference: p \n "
" [test.cpp:8]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2012-01-26 16:50:59 +01:00
2015-09-13 10:53:05 +02:00
check ( " void f(std::string s1, const std::string& s2, const std::string* s3) { \n "
" void* p = 0; \n "
" if (x) { return; } \n "
" foo(0 == s1.size()); \n "
" foo(0 == s2.size()); \n "
" foo(0 == s3->size()); \n "
" foo(s1.size() == 0); \n "
" foo(s2.size() == 0); \n "
" foo(s3->size() == 0); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::string s1, const std::string& s2) { \n "
" if (x) { return; } \n "
" foo(0 == s1[0]); \n "
" foo(0 == s2[0]); \n "
" foo(s1[0] == 0); \n "
" foo(s2[0] == 0); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(std::string s1, const std::string& s2) { \n "
" if (x) { return; } \n "
" foo(s1 == ' \\ 0'); \n "
" foo(s2 == ' \\ 0'); \n "
" foo(' \\ 0' == s1); \n "
" foo(' \\ 0' == s2); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-01-26 16:50:59 +01:00
check ( " class Bar { \n "
" std::string s; \n "
" Bar() : s(0) {} \n "
" }; \n "
" class Foo { \n "
" std::string s; \n "
" Foo(); \n "
" }; \n "
" Foo::Foo() : s(0) {} " ) ;
2012-04-23 18:26:27 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference \n "
" [test.cpp:9]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2012-04-02 12:12:02 +02:00
check ( " void f() { \n "
" std::string s = 0 == x ? \" a \" : \" b \" ; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-08-24 21:50:19 +02:00
check ( " void f() { \n "
" const std::string s = g(); \n "
" ASSERT_MESSAGE( \" Error on s \" , 0 == s.compare( \" Some text \" )); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-02-24 19:10:34 +01:00
check ( " void foo(int i, std::string s); \n "
" void bar() { \n "
" foo(0, \" \" ); \n "
" foo(0, 0); \n "
" foo(var, 0); \n "
2017-02-24 19:44:28 +01:00
" foo(var, NULL); \n "
" foo(var, nullptr); \n "
2017-02-24 19:10:34 +01:00
" foo(0, var); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference \n "
2017-02-24 19:44:28 +01:00
" [test.cpp:5]: (error) Null pointer dereference \n "
" [test.cpp:6]: (error) Null pointer dereference \n "
" [test.cpp:7]: (error) Null pointer dereference \n " , errout . str ( ) ) ;
2012-01-25 15:16:22 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointerStdStream ( ) {
2012-03-16 17:24:03 +01:00
check ( " void f(std::ifstream& is) { \n "
" char* p = 0; \n "
" is >> p; \n "
" } " ) ;
2014-05-17 16:44:44 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Possible null pointer dereference: p \n " , " " , errout . str ( ) ) ;
2012-03-16 17:24:03 +01:00
check ( " void f(const std::ostringstream& oss, char* q) { \n "
" char const* p = 0; \n " // Simplification makes detection of bug difficult
" oss << p; \n "
" oss << foo << p; \n "
" if(q == 0) \n "
" oss << foo << q; \n "
2015-07-25 14:17:55 +02:00
" } " , false ) ;
2016-01-30 20:43:21 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Null pointer dereference: p \n "
" [test.cpp:4]: (error) Null pointer dereference: p \n "
2017-05-15 20:05:11 +02:00
" [test.cpp:5] -> [test.cpp:6]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q. \n " , errout . str ( ) ) ;
2012-03-16 17:24:03 +01:00
check ( " void f(const char* p) { \n "
" if(p == 0) { \n "
" std::cout << p; \n "
" std::cerr << p; \n "
" std::cin >> p; \n "
" std::cout << abc << p; \n "
" } \n "
2015-07-25 14:17:55 +02:00
" } " , false ) ;
2017-05-15 20:05:11 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n "
" [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n "
" [test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n "
" [test.cpp:2] -> [test.cpp:6]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n " ,
" [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n "
" [test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p. \n " ,
2014-06-22 10:02:14 +02:00
errout . str ( ) ) ;
2012-03-16 17:24:03 +01:00
check ( " void f() { \n "
" void* p1 = 0; \n "
" std::cout << p1; \n " // No char*
" char* p2 = 0; \n "
" std::cin >> (int)p; \n " // result casted
" std::cout << (int)p; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2012-03-16 17:24:03 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const std::string& str) { \n "
" long long ret = 0; \n "
" std::istringstream istr(str); \n "
" istr >> std::hex >> ret; \n " // Read integer
" return ret; \n "
2012-04-30 12:36:41 +02:00
" } " , true ) ;
2012-03-16 17:24:03 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-10 19:53:20 +01:00
check ( " void f(int* i) { \n "
" if(i) return; \n "
" std::cout << i; \n " // Its no char* (#4240)
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-17 18:18:20 +02:00
2016-11-27 11:40:42 +01:00
// #5811 false positive: (error) Null pointer dereference
2014-05-17 18:18:20 +02:00
check ( " using namespace std; \n "
" std::string itoip(int ip) { \n "
" stringstream out; \n "
" out << ((ip >> 0) & 0xFF); \n "
" return out.str(); \n "
2015-07-25 14:17:55 +02:00
" }n " , true ) ;
2014-05-17 18:18:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-17 19:14:29 +02:00
// avoid regression from first fix attempt for #5811...
check ( " void deserialize(const std::string &data) { \n "
" std::istringstream iss(data); \n "
" unsigned int len = 0; \n "
" if (!(iss >> len)) \n "
" return; \n "
2015-07-25 14:17:55 +02:00
" } \n " , true ) ;
2014-05-17 19:14:29 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-03-16 17:24:03 +01:00
}
2019-04-26 11:30:09 +02:00
void nullpointerSmartPointer ( ) {
check ( " struct Fred { int x; }; \n "
" void f(std::shared_ptr<Fred> p) { \n "
" if (p) {} \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::shared_ptr<Fred> p) { \n "
" p = nullptr; \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::unique_ptr<Fred> p) { \n "
" if (p) {} \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::unique_ptr<Fred> p) { \n "
" p = nullptr; \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f() { \n "
" std::shared_ptr<Fred> p; \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::shared_ptr<Fred> p) { \n "
" p.reset(); \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::shared_ptr<Fred> p) { \n "
" Fred * pp = nullptr; \n "
" p.reset(pp); \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(Fred& f) { \n "
" std::shared_ptr<Fred> p; \n "
" p.reset(&f); \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f(std::shared_ptr<Fred> p) { \n "
" p.release(); \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
check ( " struct Fred { int x; }; \n "
" void f() { \n "
" std::shared_ptr<Fred> p(nullptr); \n "
" dostuff(p->x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Null pointer dereference: p \n " , errout . str ( ) ) ;
2019-05-05 09:51:36 +02:00
check ( " struct A {}; \n "
" void f(int n) { \n "
" std::unique_ptr<const A*[]> p; \n "
" p.reset(new const A*[n]); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-04-26 11:30:09 +02:00
}
2014-11-20 14:20:09 +01:00
void functioncall ( ) { // #3443 - function calls
2011-12-25 17:01:45 +01:00
// dereference pointer and then check if it's null
{
// function not seen
check ( " void f(int *p) { \n "
" *p = 0; \n "
" foo(p); \n "
" if (p) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// function seen (taking pointer parameter)
check ( " void foo(int *p) { } \n "
" \n "
" void f(int *p) { \n "
" *p = 0; \n "
" foo(p); \n "
" if (p) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-12-25 17:01:45 +01:00
2012-09-06 18:33:15 +02:00
// function seen (taking reference parameter)
check ( " void foo(int *&p) { } \n "
" \n "
" void f(int *p) { \n "
" *p = 0; \n "
" foo(p); \n "
" if (p) { } \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-12-25 17:01:45 +01:00
// function implementation not seen
check ( " void foo(int *p); \n "
" \n "
" void f(int *p) { \n "
" *p = 0; \n "
" foo(p); \n "
" if (p) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-12-26 07:13:10 +01:00
// inconclusive
check ( " void f(int *p) { \n "
" *p = 0; \n "
" foo(p); \n "
" if (p) { } \n "
" } " , true ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p. \n " , errout . str ( ) ) ;
2011-12-25 17:01:45 +01:00
}
// dereference struct pointer and then check if it's null
{
// function not seen
check ( " void f(struct ABC *abc) { \n "
" abc->a = 0; \n "
" foo(abc); \n "
" if (abc) { } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// function seen (taking pointer parameter)
check ( " void foo(struct ABC *abc) { } \n "
" \n "
" void f(struct ABC *abc) { \n "
" abc->a = 0; \n "
" foo(abc); \n "
" if (abc) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-12-25 17:01:45 +01:00
// function implementation not seen
check ( " void foo(struct ABC *abc); \n "
" \n "
" void f(struct ABC *abc) { \n "
" abc->a = 0; \n "
" foo(abc); \n "
" if (abc) { } \n "
" } " ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-12-26 07:13:10 +01:00
// inconclusive
check ( " void f(struct ABC *abc) { \n "
" abc->a = 0; \n "
" foo(abc); \n "
" if (abc) { } \n "
" } " , true ) ;
2017-05-15 20:05:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc. \n " , errout . str ( ) ) ;
2011-12-25 17:01:45 +01:00
}
}
2012-01-31 15:49:34 +01:00
2014-11-20 14:20:09 +01:00
void functioncalllibrary ( ) {
2014-04-02 19:39:42 +02:00
Settings settings1 ;
Tokenizer tokenizer ( & settings1 , this ) ;
2015-03-14 19:23:33 +01:00
std : : istringstream code ( " void f() { int a,b,c; x(a,b,c); } " ) ;
2013-07-15 21:57:58 +02:00
tokenizer . tokenize ( code , " test.c " ) ;
const Token * xtok = Token : : findsimplematch ( tokenizer . tokens ( ) , " x " ) ;
// nothing bad..
{
Library library ;
2013-07-22 20:21:45 +02:00
Library : : ArgumentChecks arg ;
2016-12-06 12:31:16 +01:00
library . functions [ " x " ] . argumentChecks [ 1 ] = arg ;
library . functions [ " x " ] . argumentChecks [ 2 ] = arg ;
library . functions [ " x " ] . argumentChecks [ 3 ] = arg ;
2013-07-15 21:57:58 +02:00
2017-02-24 19:10:34 +01:00
std : : list < const Token * > null ;
CheckNullPointer : : parseFunctionCall ( * xtok , null , & library ) ;
2013-07-15 21:57:58 +02:00
ASSERT_EQUALS ( 0U , null . size ( ) ) ;
}
// for 1st parameter null pointer is not ok..
{
Library library ;
2013-12-26 17:48:25 +01:00
Library : : ArgumentChecks arg ;
2016-12-06 12:31:16 +01:00
library . functions [ " x " ] . argumentChecks [ 1 ] = arg ;
library . functions [ " x " ] . argumentChecks [ 2 ] = arg ;
library . functions [ " x " ] . argumentChecks [ 3 ] = arg ;
library . functions [ " x " ] . argumentChecks [ 1 ] . notnull = true ;
2013-07-15 21:57:58 +02:00
2017-02-24 19:10:34 +01:00
std : : list < const Token * > null ;
CheckNullPointer : : parseFunctionCall ( * xtok , null , & library ) ;
2013-07-15 21:57:58 +02:00
ASSERT_EQUALS ( 1U , null . size ( ) ) ;
ASSERT_EQUALS ( " a " , null . front ( ) - > str ( ) ) ;
2015-03-14 19:23:33 +01:00
}
2013-07-15 21:57:58 +02:00
}
2012-11-21 08:56:17 +01:00
2014-11-20 14:20:09 +01:00
void functioncallDefaultArguments ( ) {
2012-11-21 08:56:17 +01:00
check ( " void f(int *p = 0) { \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
2013-04-25 09:25:56 +02:00
check ( " void f(int *p = 0) { \n "
" if (!p) \n "
" return; \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-21 08:56:17 +01:00
check ( " void f(char a, int *p = 0) { \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" printf( \" p = %d \" , *p); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" printf( \" p[1] = %d \" , p[1]); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
2016-01-20 08:42:58 +01:00
check ( " void f(int *p = 0) { \n "
" buf[p] = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-21 08:56:17 +01:00
check ( " void f(int *p = 0) { \n "
" if (p != 0 && bar()) \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-11-21 08:56:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p) { \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" if (p != 0) \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-11-21 08:56:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-01-10 08:22:54 +01:00
check ( " void f(int *p = 0) { \n "
" int y; \n "
" if (p == 0) \n "
" p = &y; \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2013-01-10 08:22:54 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-11-21 08:56:17 +01:00
check ( " void f(int *p = 0) { \n "
" if (a != 0) \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " , true ) ;
2015-02-01 15:05:00 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , " " , errout . str ( ) ) ;
2012-11-21 08:56:17 +01:00
check ( " void f(int *p = 0) { \n "
" p = a; \n "
2013-04-15 19:00:15 +02:00
" *p = 0; \n " // <- don't simplify and verify
2015-07-25 14:17:55 +02:00
" } " ) ;
2012-11-21 08:56:17 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" p += a; \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-02-28 08:45:21 +01:00
check ( " int f(int *p = 0) { \n "
" if (p == 0) { \n "
" return 0; \n "
" } \n "
" return *p; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2013-02-28 08:45:21 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
2014-05-22 19:48:00 +02:00
" std::cout << p ? *p : 0; \n " // Due to operator precedence, this is equivalent to: (std::cout << p) ? *p : 0;
" } " ) ;
2015-05-24 17:02:00 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ; // Check the first branch of ternary
2014-05-22 19:48:00 +02:00
check ( " void f(char *p = 0) { \n "
" std::cout << p ? *p : 0; \n " // Due to operator precedence, this is equivalent to: (std::cout << p) ? *p : 0;
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" std::cout << (p ? *p : 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" std::cout << p; \n "
2013-02-28 08:45:21 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" std::cout << (p && p[0] ? *p : 42); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void isEmpty(int *p = 0) { \n "
2013-04-15 19:00:15 +02:00
" return p && *p; \n "
2013-02-28 08:45:21 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void g(int *p = 0) { \n "
2013-04-15 19:00:15 +02:00
" return !p || *p; \n "
2013-02-28 08:45:21 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-04-25 09:25:56 +02:00
// bar may initialize p but be can't know for sure without knowing
// if p is passed in by reference and is modified by bar()
check ( " void f(int *p = 0) { \n "
" bar(p); \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
2019-02-28 17:02:46 +01:00
" printf( \" %p \" , p); \n "
2013-04-25 09:25:56 +02:00
" *p = 0; \n "
2015-02-01 15:05:00 +01:00
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (warning, inconclusive) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
2013-04-25 09:25:56 +02:00
// The init() function may or may not initialize p, but since the address
// of p is passed in, it's a good bet that p may be modified and
// so we should not report an error.
check ( " void f(int *p = 0) { \n "
" init(&p); \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void init(int* &g); \n "
" void f(int *p = 0) { \n "
" init(p); \n "
" *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" if (p == 0) { \n "
" init(&p); \n "
" } \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2013-04-25 09:25:56 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int *p = 0) { \n "
" if (p == 0) { \n "
" throw SomeException; \n "
" } \n "
" *p = 0; \n "
2015-07-25 14:17:55 +02:00
" } " ) ;
2013-04-25 09:25:56 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-22 19:48:00 +02:00
check ( " void foo(int *p = 0) { \n "
" int var1 = x ? *p : 5; \n "
" } " ) ;
2015-02-01 15:05:00 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p \n " , errout . str ( ) ) ;
2012-11-21 08:56:17 +01:00
}
2014-11-20 14:20:09 +01:00
void nullpointer_internal_error ( ) { // ticket #5080
2013-10-12 10:50:59 +02:00
check ( " struct A { unsigned int size; }; \n "
" struct B { struct A *a; }; \n "
" void f(struct B *b) { \n "
" unsigned int j; \n "
" for (j = 0; j < b[0].a->size; ++j) { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-07-31 21:15:43 +02:00
void ticket6505 ( ) {
check ( " void foo(MythSocket *socket) { \n "
2016-10-23 13:54:44 +02:00
" bool do_write=0; \n "
2015-07-31 21:15:43 +02:00
" if (socket) { \n "
" do_write=something(); \n "
" } \n "
" if (do_write) { \n "
" socket->func(); \n "
" } \n "
" } \n "
" void bar() { \n "
" foo(0); \n "
" } \n " , true , " test.c " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-10-09 15:15:29 +02:00
void subtract ( ) {
check ( " void foo(char *s) { \n "
" p = s - 20; \n "
" } \n "
" void bar() { foo(0); } \n " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Overflow in pointer arithmetic, NULL pointer is subtracted. \n " , " " , errout . str ( ) ) ;
2016-10-09 15:15:29 +02:00
check ( " void foo(char *s) { \n "
" if (!s) {} \n "
" p = s - 20; \n "
" } \n " ) ;
2018-05-01 17:30:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is overflow in pointer subtraction. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" s -= 20; \n "
" } \n "
" void bar() { foo(0); } \n " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Overflow in pointer arithmetic, NULL pointer is subtracted. \n " , " " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" if (!s) {} \n "
" s -= 20; \n "
" } \n " ) ;
2018-05-01 17:30:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is overflow in pointer subtraction. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " int* f8() { int *x = NULL; return --x; } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (error) Overflow in pointer arithmetic, NULL pointer is subtracted. \n " , errout . str ( ) ) ;
check ( " int* f9() { int *x = NULL; return x--; } " ) ;
ASSERT_EQUALS ( " [test.cpp:1]: (error) Overflow in pointer arithmetic, NULL pointer is subtracted. \n " , errout . str ( ) ) ;
}
void addNull ( ) {
check ( " void foo(char *s) { \n "
" char * p = s + 20; \n "
" } \n "
" void bar() { foo(0); } \n " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Pointer addition with NULL pointer. \n " , " " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" if (!s) {} \n "
" char * p = s + 20; \n "
" } \n " ) ;
2018-05-01 17:30:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is pointer arithmetic with NULL pointer. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" char * p = 20 + s; \n "
" } \n "
" void bar() { foo(0); } \n " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Pointer addition with NULL pointer. \n " , " " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" if (!s) {} \n "
" char * p = 20 + s; \n "
" } \n " ) ;
2018-05-01 17:30:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is pointer arithmetic with NULL pointer. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" s += 20; \n "
" } \n "
" void bar() { foo(0); } \n " ) ;
2018-12-18 14:36:49 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Pointer addition with NULL pointer. \n " , " " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " void foo(char *s) { \n "
" if (!s) {} \n "
" s += 20; \n "
" } \n " ) ;
2018-05-01 17:30:29 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is pointer arithmetic with NULL pointer. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " int* f7() { int *x = NULL; return ++x; } " ) ;
2018-05-02 12:57:24 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (error) Pointer addition with NULL pointer. \n " , errout . str ( ) ) ;
2018-04-03 21:32:37 +02:00
check ( " int* f10() { int *x = NULL; return x++; } " ) ;
2018-05-02 12:57:24 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (error) Pointer addition with NULL pointer. \n " , errout . str ( ) ) ;
2018-05-09 09:06:49 +02:00
check ( " class foo {}; \n "
" const char* get() const { return 0; } \n "
" void f(foo x) { if (get()) x += get(); } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-10-09 15:15:29 +02:00
}
2018-12-18 07:56:33 +01:00
void ctu ( const char code [ ] ) {
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
2018-12-25 21:11:23 +01:00
CTU : : FileInfo * ctu = CTU : : getFileInfo ( & tokenizer ) ;
2018-12-18 07:56:33 +01:00
// Check code..
std : : list < Check : : FileInfo * > fileInfo ;
2018-12-25 21:11:23 +01:00
CheckNullPointer check ( & tokenizer , & settings , this ) ;
2018-12-18 07:56:33 +01:00
fileInfo . push_back ( check . getFileInfo ( & tokenizer , & settings ) ) ;
2018-12-25 21:11:23 +01:00
check . analyseWholeProgram ( ctu , fileInfo , settings , * this ) ;
2018-12-18 07:56:33 +01:00
while ( ! fileInfo . empty ( ) ) {
delete fileInfo . back ( ) ;
fileInfo . pop_back ( ) ;
}
2018-12-25 21:11:23 +01:00
delete ctu ;
2018-12-18 07:56:33 +01:00
}
void ctu ( ) {
2018-12-25 12:04:01 +01:00
setMultiline ( ) ;
2018-12-18 07:56:33 +01:00
ctu ( " void f(int *fp) { \n "
" a = *fp; \n "
" } \n "
" int main() { \n "
" int *p = 0; \n "
" f(p); \n "
" } " ) ;
2018-12-25 12:04:01 +01:00
ASSERT_EQUALS ( " test.cpp:2:error:Null pointer dereference: fp \n "
2018-12-30 18:31:37 +01:00
" test.cpp:5:note:Assignment 'p=0', assigned value is 0 \n "
2018-12-25 12:04:01 +01:00
" test.cpp:6:note:Calling function f, 1st argument is null \n "
" test.cpp:2:note:Dereferencing argument fp that is null \n " , errout . str ( ) ) ;
2018-12-18 07:56:33 +01:00
ctu ( " void use(int *p) { a = *p + 3; } \n "
" void call(int x, int *p) { x++; use(p); } \n "
" int main() { \n "
" call(4,0); \n "
" } " ) ;
2018-12-25 12:04:01 +01:00
ASSERT_EQUALS ( " test.cpp:1:error:Null pointer dereference: p \n "
" test.cpp:4:note:Calling function call, 2nd argument is null \n "
2018-12-30 16:23:25 +01:00
" test.cpp:2:note:Calling function use, 1st argument is null \n "
2018-12-25 12:04:01 +01:00
" test.cpp:1:note:Dereferencing argument p that is null \n " , errout . str ( ) ) ;
2018-12-18 07:56:33 +01:00
ctu ( " void dostuff(int *x, int *y) { \n "
" if (!var) \n "
" return -1; \n " // <- early return
" *x = *y; \n "
" } \n "
" \n "
" void f() { \n "
" dostuff(a, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
ctu ( " void dostuff(int *x, int *y) { \n "
" if (cond) \n "
" *y = -1; \n " // <- conditionally written
" *x = *y; \n "
" } \n "
" \n "
" void f() { \n "
" dostuff(a, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-31 08:16:21 +01:00
2018-12-31 08:24:39 +01:00
// else
ctu ( " void dostuff(int mask, int *p) { \n "
" if (mask == 13) ; \n "
" else *p = 45; \n "
" } \n "
" \n "
" void f() { \n "
" dostuff(0, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-31 08:16:21 +01:00
// ?, &&, ||
ctu ( " void dostuff(int mask, int *p) { \n "
" x = (mask & 1) ? *p : 0; \n "
" } \n "
" \n "
" void f() { \n "
" dostuff(0, 0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-12-18 07:56:33 +01:00
}
2010-10-31 11:51:25 +01:00
} ;
REGISTER_TEST ( TestNullPointer )