Fix 10617, 9824: conditions in expanded macro (#3578)
This commit is contained in:
parent
085d25f1b1
commit
33ad30f4da
2
Makefile
2
Makefile
|
@ -621,7 +621,7 @@ test/testbool.o: test/testbool.cpp lib/astutils.h lib/check.h lib/checkbool.h li
|
|||
test/testboost.o: test/testboost.cpp lib/astutils.h lib/check.h lib/checkboost.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
|
||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testboost.o test/testboost.cpp
|
||||
|
||||
test/testbufferoverrun.o: test/testbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
|
||||
test/testbufferoverrun.o: test/testbufferoverrun.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
|
||||
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testbufferoverrun.o test/testbufferoverrun.cpp
|
||||
|
||||
test/testbughuntingchecks.o: test/testbughuntingchecks.cpp lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
|
||||
|
|
|
@ -5224,8 +5224,12 @@ struct ConditionHandler {
|
|||
if (!top)
|
||||
return;
|
||||
|
||||
if (top->previous()->isExpandedMacro())
|
||||
return;
|
||||
if (top->previous()->isExpandedMacro()) {
|
||||
for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
|
||||
for (ValueFlow::Value& v : *values)
|
||||
v.macro = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Token::Match(top->previous(), "if|while|for ("))
|
||||
return;
|
||||
|
@ -7545,6 +7549,7 @@ ValueFlow::Value::Value(const Token* c, long long val, Bound b)
|
|||
varId(0),
|
||||
safe(false),
|
||||
conditional(false),
|
||||
macro(false),
|
||||
defaultArg(false),
|
||||
indirect(0),
|
||||
path(0),
|
||||
|
|
|
@ -98,6 +98,7 @@ namespace ValueFlow {
|
|||
varId(0U),
|
||||
safe(false),
|
||||
conditional(false),
|
||||
macro(false),
|
||||
defaultArg(false),
|
||||
indirect(0),
|
||||
path(0),
|
||||
|
@ -346,6 +347,9 @@ namespace ValueFlow {
|
|||
/** Conditional value */
|
||||
bool conditional;
|
||||
|
||||
/** Value is is from an expanded macro */
|
||||
bool macro;
|
||||
|
||||
/** Is this value passed as default parameter to the function? */
|
||||
bool defaultArg;
|
||||
|
||||
|
|
|
@ -22,14 +22,15 @@
|
|||
#include "config.h"
|
||||
#include "ctu.h"
|
||||
#include "library.h"
|
||||
#include "preprocessor.h"
|
||||
#include "settings.h"
|
||||
#include "testsuite.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include <list>
|
||||
#include <simplecpp.h>
|
||||
#include <string>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
class TestBufferOverrun : public TestFixture {
|
||||
public:
|
||||
|
@ -67,6 +68,45 @@ private:
|
|||
checkBufferOverrun.runChecks(&tokenizer, &settings, this);
|
||||
}
|
||||
|
||||
void checkP(const char code[], const char* filename = "test.cpp")
|
||||
{
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
Settings* settings = &settings0;
|
||||
settings->severity.enable(Severity::style);
|
||||
settings->severity.enable(Severity::warning);
|
||||
settings->severity.enable(Severity::portability);
|
||||
settings->severity.enable(Severity::performance);
|
||||
settings->standards.c = Standards::CLatest;
|
||||
settings->standards.cpp = Standards::CPPLatest;
|
||||
settings->certainty.enable(Certainty::inconclusive);
|
||||
settings->certainty.disable(Certainty::experimental);
|
||||
|
||||
// Raw tokens..
|
||||
std::vector<std::string> files(1, filename);
|
||||
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());
|
||||
|
||||
Preprocessor preprocessor(*settings, nullptr);
|
||||
preprocessor.setDirectives(tokens1);
|
||||
|
||||
// Tokenizer..
|
||||
Tokenizer tokenizer(settings, this);
|
||||
tokenizer.createTokens(std::move(tokens2));
|
||||
tokenizer.simplifyTokens1("");
|
||||
tokenizer.setPreprocessor(&preprocessor);
|
||||
|
||||
// Check for buffer overruns..
|
||||
CheckBufferOverrun checkBufferOverrun(&tokenizer, settings, this);
|
||||
checkBufferOverrun.runChecks(&tokenizer, settings, this);
|
||||
}
|
||||
|
||||
void run() OVERRIDE {
|
||||
LOAD_LIB_2(settings0.library, "std.cfg");
|
||||
|
||||
|
@ -136,6 +176,7 @@ private:
|
|||
TEST_CASE(array_index_57); // #10023
|
||||
TEST_CASE(array_index_58); // #7524
|
||||
TEST_CASE(array_index_59); // #10413
|
||||
TEST_CASE(array_index_60); // #10617, #9824
|
||||
TEST_CASE(array_index_multidim);
|
||||
TEST_CASE(array_index_switch_in_for);
|
||||
TEST_CASE(array_index_for_in_for); // FP: #2634
|
||||
|
@ -1665,6 +1706,29 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void array_index_60()
|
||||
{
|
||||
checkP("#define CKR(B) if (!(B)) { return -1; }\n"
|
||||
"int f(int i) {\n"
|
||||
" const int A[3] = {};\n"
|
||||
" CKR(i < 3);\n"
|
||||
" if (i > 0)\n"
|
||||
" i = A[i];\n"
|
||||
" return i;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkP("#define ASSERT(expression, action) if (expression) {action;}\n"
|
||||
"int array[5];\n"
|
||||
"void func (int index) {\n"
|
||||
" ASSERT(index > 5, return);\n"
|
||||
" array[index]++;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(
|
||||
"[test.cpp:4] -> [test.cpp:5]: (warning) Either the condition 'index>5' is redundant or the array 'array[5]' is accessed at index 5, which is out of bounds.\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
void array_index_multidim() {
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue