CTU: more warnings
This commit is contained in:
parent
c8901e9bab
commit
91a580cbd7
|
@ -660,18 +660,23 @@ bool CheckNullPointer::analyseWholeProgram(const CTU::FileInfo *ctu, const std::
|
||||||
if (!fi)
|
if (!fi)
|
||||||
continue;
|
continue;
|
||||||
for (const CTU::FileInfo::UnsafeUsage &unsafeUsage : fi->unsafeUsage) {
|
for (const CTU::FileInfo::UnsafeUsage &unsafeUsage : fi->unsafeUsage) {
|
||||||
|
for (int warning = 0; warning <= 1; warning++) {
|
||||||
|
if (warning == 1 && !settings.isEnabled(Settings::WARNING))
|
||||||
|
break;
|
||||||
|
|
||||||
const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList =
|
const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList =
|
||||||
ctu->getErrorPath(CTU::FileInfo::InvalidValueType::null,
|
ctu->getErrorPath(CTU::FileInfo::InvalidValueType::null,
|
||||||
unsafeUsage,
|
unsafeUsage,
|
||||||
callsMap,
|
callsMap,
|
||||||
"Dereferencing argument ARG that is null",
|
"Dereferencing argument ARG that is null",
|
||||||
nullptr);
|
nullptr,
|
||||||
|
warning);
|
||||||
if (locationList.empty())
|
if (locationList.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||||
emptyString,
|
emptyString,
|
||||||
Severity::error,
|
warning ? Severity::warning : Severity::error,
|
||||||
"Null pointer dereference: " + unsafeUsage.myArgumentName,
|
"Null pointer dereference: " + unsafeUsage.myArgumentName,
|
||||||
"ctunullpointer",
|
"ctunullpointer",
|
||||||
CWE476, false);
|
CWE476, false);
|
||||||
|
@ -680,6 +685,9 @@ bool CheckNullPointer::analyseWholeProgram(const CTU::FileInfo *ctu, const std::
|
||||||
foundErrors = true;
|
foundErrors = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (foundErrors)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundErrors;
|
return foundErrors;
|
||||||
|
|
|
@ -1339,7 +1339,8 @@ bool CheckUninitVar::analyseWholeProgram(const CTU::FileInfo *ctu, const std::li
|
||||||
unsafeUsage,
|
unsafeUsage,
|
||||||
callsMap,
|
callsMap,
|
||||||
"Using argument ARG",
|
"Using argument ARG",
|
||||||
&functionCall);
|
&functionCall,
|
||||||
|
false);
|
||||||
if (locationList.empty())
|
if (locationList.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
70
lib/ctu.cpp
70
lib/ctu.cpp
|
@ -30,8 +30,10 @@ static const char ATTR_CALL_ARGNR[] = "call-argnr";
|
||||||
static const char ATTR_CALL_ARGEXPR[] = "call-argexpr";
|
static const char ATTR_CALL_ARGEXPR[] = "call-argexpr";
|
||||||
static const char ATTR_CALL_ARGVALUETYPE[] = "call-argvaluetype";
|
static const char ATTR_CALL_ARGVALUETYPE[] = "call-argvaluetype";
|
||||||
static const char ATTR_CALL_ARGVALUE[] = "call-argvalue";
|
static const char ATTR_CALL_ARGVALUE[] = "call-argvalue";
|
||||||
static const char ATTR_LOC_FILENAME[] = "loc-filename";
|
static const char ATTR_WARNING[] = "warning";
|
||||||
static const char ATTR_LOC_LINENR[] = "loc-linenr";
|
static const char ATTR_LOC_FILENAME[] = "filename";
|
||||||
|
static const char ATTR_LOC_LINENR[] = "linenr";
|
||||||
|
static const char ATTR_INFO[] = "info";
|
||||||
static const char ATTR_MY_ID[] = "my-id";
|
static const char ATTR_MY_ID[] = "my-id";
|
||||||
static const char ATTR_MY_ARGNR[] = "my-argnr";
|
static const char ATTR_MY_ARGNR[] = "my-argnr";
|
||||||
static const char ATTR_MY_ARGNAME[] = "my-argname";
|
static const char ATTR_MY_ARGNAME[] = "my-argname";
|
||||||
|
@ -83,8 +85,20 @@ std::string CTU::FileInfo::FunctionCall::toXmlString() const
|
||||||
<< toBaseXmlString()
|
<< toBaseXmlString()
|
||||||
<< " " << ATTR_CALL_ARGEXPR << "=\"" << callArgumentExpression << "\""
|
<< " " << ATTR_CALL_ARGEXPR << "=\"" << callArgumentExpression << "\""
|
||||||
<< " " << ATTR_CALL_ARGVALUETYPE << "=\"" << callValueType << "\""
|
<< " " << ATTR_CALL_ARGVALUETYPE << "=\"" << callValueType << "\""
|
||||||
<< " " << ATTR_CALL_ARGVALUE << "=\"" << callArgValue << "\""
|
<< " " << ATTR_CALL_ARGVALUE << "=\"" << callArgValue << "\"";
|
||||||
<< "/>";
|
if (warning)
|
||||||
|
out << " " << ATTR_WARNING << "=\"true\"";
|
||||||
|
if (callValuePath.empty())
|
||||||
|
out << "/>";
|
||||||
|
else {
|
||||||
|
out << ">\n";
|
||||||
|
for (const ErrorLogger::ErrorMessage::FileLocation &loc : callValuePath)
|
||||||
|
out << " <path"
|
||||||
|
<< " " << ATTR_LOC_FILENAME << "=\"" << loc.getfile() << "\""
|
||||||
|
<< " " << ATTR_LOC_LINENR << "=\"" << loc.line << "\""
|
||||||
|
<< " " << ATTR_INFO << "=\"" << loc.getinfo() << "\"/>\n";
|
||||||
|
out << "</function-call>";
|
||||||
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +184,16 @@ bool CTU::FileInfo::FunctionCall::loadFromXml(const tinyxml2::XMLElement *e)
|
||||||
callArgumentExpression = readAttrString(e, ATTR_CALL_ARGEXPR, &error);
|
callArgumentExpression = readAttrString(e, ATTR_CALL_ARGEXPR, &error);
|
||||||
callValueType = (ValueFlow::Value::ValueType)readAttrInt(e, ATTR_CALL_ARGVALUETYPE, &error);
|
callValueType = (ValueFlow::Value::ValueType)readAttrInt(e, ATTR_CALL_ARGVALUETYPE, &error);
|
||||||
callArgValue = readAttrInt(e, ATTR_CALL_ARGVALUE, &error);
|
callArgValue = readAttrInt(e, ATTR_CALL_ARGVALUE, &error);
|
||||||
|
const char *w = e->Attribute(ATTR_WARNING);
|
||||||
|
warning = w && std::strcmp(w, "true") == 0;
|
||||||
|
for (const tinyxml2::XMLElement *e2 = e->FirstChildElement(); !error && e2; e2 = e2->NextSiblingElement()) {
|
||||||
|
if (std::strcmp(e2->Name(), "path") != 0)
|
||||||
|
continue;
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||||
|
loc.setfile(readAttrString(e2, ATTR_LOC_FILENAME, &error));
|
||||||
|
loc.line = readAttrInt(e2, ATTR_LOC_LINENR, &error);
|
||||||
|
loc.setinfo(readAttrString(e2, ATTR_INFO, &error));
|
||||||
|
}
|
||||||
return !error;
|
return !error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +304,9 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer)
|
||||||
const Token *argtok = args[argnr];
|
const Token *argtok = args[argnr];
|
||||||
if (!argtok)
|
if (!argtok)
|
||||||
continue;
|
continue;
|
||||||
if (argtok->hasKnownIntValue()) {
|
for (const ValueFlow::Value &value : argtok->values()) {
|
||||||
|
if (!value.isIntValue() || value.intvalue != 0 || value.isInconclusive())
|
||||||
|
continue;
|
||||||
struct FileInfo::FunctionCall functionCall;
|
struct FileInfo::FunctionCall functionCall;
|
||||||
functionCall.callValueType = ValueFlow::Value::INT;
|
functionCall.callValueType = ValueFlow::Value::INT;
|
||||||
functionCall.callId = getFunctionId(tokenizer, tok->astOperand1()->function());
|
functionCall.callId = getFunctionId(tokenizer, tok->astOperand1()->function());
|
||||||
|
@ -289,9 +315,16 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer)
|
||||||
functionCall.location.linenr = tok->linenr();
|
functionCall.location.linenr = tok->linenr();
|
||||||
functionCall.callArgNr = argnr + 1;
|
functionCall.callArgNr = argnr + 1;
|
||||||
functionCall.callArgumentExpression = argtok->expressionString();
|
functionCall.callArgumentExpression = argtok->expressionString();
|
||||||
functionCall.callArgValue = argtok->values().front().intvalue;
|
functionCall.callArgValue = value.intvalue;
|
||||||
|
functionCall.warning = (value.condition != nullptr);
|
||||||
|
for (const ErrorPathItem &i : value.errorPath) {
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||||
|
loc.setfile(tokenizer->list.file(i.first));
|
||||||
|
loc.line = i.first->linenr();
|
||||||
|
loc.setinfo(i.second);
|
||||||
|
functionCall.callValuePath.push_back(loc);
|
||||||
|
}
|
||||||
fileInfo->functionCalls.push_back(functionCall);
|
fileInfo->functionCalls.push_back(functionCall);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
// pointer to uninitialized data..
|
// pointer to uninitialized data..
|
||||||
if (!argtok->isUnaryOp("&"))
|
if (!argtok->isUnaryOp("&"))
|
||||||
|
@ -312,6 +345,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer)
|
||||||
functionCall.callArgNr = argnr + 1;
|
functionCall.callArgNr = argnr + 1;
|
||||||
functionCall.callArgValue = 0;
|
functionCall.callArgValue = 0;
|
||||||
functionCall.callArgumentExpression = argtok->expressionString();
|
functionCall.callArgumentExpression = argtok->expressionString();
|
||||||
|
functionCall.warning = false;
|
||||||
fileInfo->functionCalls.push_back(functionCall);
|
fileInfo->functionCalls.push_back(functionCall);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +419,8 @@ static bool findPath(const std::string &callId,
|
||||||
CTU::FileInfo::InvalidValueType invalidValue,
|
CTU::FileInfo::InvalidValueType invalidValue,
|
||||||
const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap,
|
const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap,
|
||||||
const CTU::FileInfo::CallBase *path[10],
|
const CTU::FileInfo::CallBase *path[10],
|
||||||
int index)
|
int index,
|
||||||
|
bool warning)
|
||||||
{
|
{
|
||||||
if (index >= 10)
|
if (index >= 10)
|
||||||
return false;
|
return false;
|
||||||
|
@ -400,6 +435,8 @@ static bool findPath(const std::string &callId,
|
||||||
|
|
||||||
const CTU::FileInfo::FunctionCall *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(c);
|
const CTU::FileInfo::FunctionCall *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(c);
|
||||||
if (functionCall) {
|
if (functionCall) {
|
||||||
|
if (!warning && functionCall->warning)
|
||||||
|
continue;
|
||||||
switch (invalidValue) {
|
switch (invalidValue) {
|
||||||
case CTU::FileInfo::InvalidValueType::null:
|
case CTU::FileInfo::InvalidValueType::null:
|
||||||
if (functionCall->callValueType != ValueFlow::Value::INT || functionCall->callArgValue != 0)
|
if (functionCall->callValueType != ValueFlow::Value::INT || functionCall->callArgValue != 0)
|
||||||
|
@ -418,7 +455,7 @@ static bool findPath(const std::string &callId,
|
||||||
if (!nestedCall)
|
if (!nestedCall)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (findPath(nestedCall->myId, nestedCall->myArgNr, invalidValue, callsMap, path, index + 1)) {
|
if (findPath(nestedCall->myId, nestedCall->myArgNr, invalidValue, callsMap, path, index + 1, warning)) {
|
||||||
path[index] = nestedCall;
|
path[index] = nestedCall;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -431,13 +468,14 @@ std::list<ErrorLogger::ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(I
|
||||||
const CTU::FileInfo::UnsafeUsage &unsafeUsage,
|
const CTU::FileInfo::UnsafeUsage &unsafeUsage,
|
||||||
const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap,
|
const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap,
|
||||||
const char info[],
|
const char info[],
|
||||||
const FunctionCall * * const functionCallPtr) const
|
const FunctionCall * * const functionCallPtr,
|
||||||
|
bool warning) const
|
||||||
{
|
{
|
||||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||||
|
|
||||||
const CTU::FileInfo::CallBase *path[10] = {0};
|
const CTU::FileInfo::CallBase *path[10] = {0};
|
||||||
|
|
||||||
if (!findPath(unsafeUsage.myId, unsafeUsage.myArgNr, invalidValue, callsMap, path, 0))
|
if (!findPath(unsafeUsage.myId, unsafeUsage.myArgNr, invalidValue, callsMap, path, 0, warning))
|
||||||
return locationList;
|
return locationList;
|
||||||
|
|
||||||
const std::string value1 = (invalidValue == InvalidValueType::null) ? "null" : "uninitialized";
|
const std::string value1 = (invalidValue == InvalidValueType::null) ? "null" : "uninitialized";
|
||||||
|
@ -446,8 +484,14 @@ std::list<ErrorLogger::ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(I
|
||||||
if (!path[index])
|
if (!path[index])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (functionCallPtr && !*functionCallPtr)
|
const CTU::FileInfo::FunctionCall *functionCall = dynamic_cast<const CTU::FileInfo::FunctionCall *>(path[index]);
|
||||||
*functionCallPtr = dynamic_cast<const CTU::FileInfo::FunctionCall *>(path[index]);
|
|
||||||
|
if (functionCall) {
|
||||||
|
if (functionCallPtr)
|
||||||
|
*functionCallPtr = functionCall;
|
||||||
|
for (const ErrorLogger::ErrorMessage::FileLocation &loc : functionCall->callValuePath)
|
||||||
|
locationList.push_back(loc);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::FileLocation fileLoc;
|
ErrorLogger::ErrorMessage::FileLocation fileLoc;
|
||||||
fileLoc.setfile(path[index]->location.fileName);
|
fileLoc.setfile(path[index]->location.fileName);
|
||||||
|
|
|
@ -75,8 +75,10 @@ namespace CTU {
|
||||||
class FunctionCall : public CallBase {
|
class FunctionCall : public CallBase {
|
||||||
public:
|
public:
|
||||||
std::string callArgumentExpression;
|
std::string callArgumentExpression;
|
||||||
long long callArgValue;
|
MathLib::bigint callArgValue;
|
||||||
ValueFlow::Value::ValueType callValueType;
|
ValueFlow::Value::ValueType callValueType;
|
||||||
|
std::vector<ErrorLogger::ErrorMessage::FileLocation> callValuePath;
|
||||||
|
bool warning;
|
||||||
|
|
||||||
std::string toXmlString() const;
|
std::string toXmlString() const;
|
||||||
bool loadFromXml(const tinyxml2::XMLElement *xmlElement);
|
bool loadFromXml(const tinyxml2::XMLElement *xmlElement);
|
||||||
|
@ -111,7 +113,8 @@ namespace CTU {
|
||||||
const UnsafeUsage &unsafeUsage,
|
const UnsafeUsage &unsafeUsage,
|
||||||
const std::map<std::string, std::list<const CallBase *>> &callsMap,
|
const std::map<std::string, std::list<const CallBase *>> &callsMap,
|
||||||
const char info[],
|
const char info[],
|
||||||
const FunctionCall * * const functionCallPtr) const;
|
const FunctionCall * * const functionCallPtr,
|
||||||
|
bool warning) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
CPPCHECKLIB std::string toString(const std::list<FileInfo::UnsafeUsage> &unsafeUsage);
|
CPPCHECKLIB std::string toString(const std::list<FileInfo::UnsafeUsage> &unsafeUsage);
|
||||||
|
|
|
@ -2705,6 +2705,7 @@ private:
|
||||||
" f(p);\n"
|
" f(p);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("test.cpp:2:error:Null pointer dereference: fp\n"
|
ASSERT_EQUALS("test.cpp:2:error:Null pointer dereference: fp\n"
|
||||||
|
"test.cpp:5:note:Assignment 'p=0', assigned value is 0\n"
|
||||||
"test.cpp:6:note:Calling function f, 1st argument is null\n"
|
"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());
|
"test.cpp:2:note:Dereferencing argument fp that is null\n", errout.str());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue