CTU: Refactoring; getErrorPath

This commit is contained in:
Daniel Marjamäki 2018-12-26 15:56:10 +01:00
parent e39be48c92
commit a6e227a73c
4 changed files with 92 additions and 74 deletions

View File

@ -593,10 +593,7 @@ void CheckNullPointer::arithmeticError(const Token *tok, const ValueFlow::Value
std::string CheckNullPointer::MyFileInfo::toString() const std::string CheckNullPointer::MyFileInfo::toString() const
{ {
std::ostringstream ret; return CTU::toString(unsafeUsage);
for (const CTU::FileInfo::UnsafeUsage &u : unsafeUsage)
ret << u.toString();
return ret.str();
} }
bool CheckNullPointer::isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const bool CheckNullPointer::isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const
@ -676,30 +673,25 @@ 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 (const CTU::FileInfo::FunctionCall &functionCall : ctu->functionCalls) { const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList =
if (functionCall.valueType != ValueFlow::Value::ValueType::INT) ctu->getErrorPath(CTU::FileInfo::InvalidValueType::null,
continue; unsafeUsage,
if (functionCall.argvalue != 0) nestedCallsMap,
continue; "Dereferencing argument ARG that is null",
nullptr);
if (locationList.empty())
continue;
const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList = const ErrorLogger::ErrorMessage errmsg(locationList,
ctu->getErrorPath(functionCall, emptyString,
unsafeUsage, Severity::error,
nestedCallsMap, "Null pointer dereference: " + unsafeUsage.argumentName,
"Dereferencing argument ARG that is null"); "ctunullpointer",
if (locationList.empty()) CWE476, false);
continue; errorLogger.reportErr(errmsg);
const ErrorLogger::ErrorMessage errmsg(locationList, foundErrors = true;
emptyString, break;
Severity::error,
"Null pointer dereference: " + unsafeUsage.argumentName,
"ctunullpointer",
CWE476, false);
errorLogger.reportErr(errmsg);
foundErrors = true;
}
} }
} }

View File

@ -1281,10 +1281,7 @@ void CheckUninitVar::deadPointerError(const Token *pointer, const Token *alias)
std::string CheckUninitVar::MyFileInfo::toString() const std::string CheckUninitVar::MyFileInfo::toString() const
{ {
std::ostringstream ret; return CTU::toString(unsafeUsage);
for (const CTU::FileInfo::UnsafeUsage &u : unsafeUsage)
ret << u.toString();
return ret.str();
} }
bool CheckUninitVar::isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const bool CheckUninitVar::isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const
@ -1330,7 +1327,6 @@ Check::FileInfo *CheckUninitVar::getFileInfo() const
const Function *const function = scope.function; const Function *const function = scope.function;
// "Unsafe" functions unconditionally reads data before it is written.. // "Unsafe" functions unconditionally reads data before it is written..
CheckNullPointer checkNullPointer(mTokenizer, mSettings, mErrorLogger);
for (int argnr = 0; argnr < function->argCount(); ++argnr) { for (int argnr = 0; argnr < function->argCount(); ++argnr) {
const Token *tok; const Token *tok;
if (isUnsafeFunction(&scope, argnr, &tok)) if (isUnsafeFunction(&scope, argnr, &tok))
@ -1366,28 +1362,27 @@ bool CheckUninitVar::analyseWholeProgram(const CTU::FileInfo *ctu, const std::li
if (!fi) if (!fi)
continue; continue;
for (const CTU::FileInfo::UnsafeUsage &unsafeUsage : fi->unsafeUsage) { for (const CTU::FileInfo::UnsafeUsage &unsafeUsage : fi->unsafeUsage) {
for (const CTU::FileInfo::FunctionCall &functionCall : ctu->functionCalls) { const CTU::FileInfo::FunctionCall *functionCall = nullptr;
if (functionCall.valueType != ValueFlow::Value::ValueType::UNINIT)
continue;
const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList = const std::list<ErrorLogger::ErrorMessage::FileLocation> &locationList =
ctu->getErrorPath(functionCall, ctu->getErrorPath(CTU::FileInfo::InvalidValueType::uninit,
unsafeUsage, unsafeUsage,
nestedCallsMap, nestedCallsMap,
"Using argument ARG"); "Using argument ARG",
if (locationList.empty()) &functionCall);
continue; if (locationList.empty())
continue;
const ErrorLogger::ErrorMessage errmsg(locationList, const ErrorLogger::ErrorMessage errmsg(locationList,
emptyString, emptyString,
Severity::error, Severity::error,
"Using argument " + unsafeUsage.argumentName + " that points at uninitialized variable " + functionCall.argumentExpression, "Using argument " + unsafeUsage.argumentName + " that points at uninitialized variable " + functionCall->argumentExpression,
"ctuuninitvar", "ctuuninitvar",
CWE908, false); CWE908, false);
errorLogger.reportErr(errmsg); errorLogger.reportErr(errmsg);
foundErrors = true; foundErrors = true;
} break;
} }
} }
return foundErrors; return foundErrors;

View File

@ -82,6 +82,14 @@ std::string CTU::FileInfo::UnsafeUsage::toString() const
return out.str(); return out.str();
} }
std::string CTU::toString(const std::list<CTU::FileInfo::UnsafeUsage> &unsafeUsage)
{
std::ostringstream ret;
for (const CTU::FileInfo::UnsafeUsage &u : unsafeUsage)
ret << u.toString();
return ret.str();
}
CTU::FileInfo::NestedCall::NestedCall(const Tokenizer *tokenizer, const Scope *scope, unsigned int argnr_, const Token *tok) CTU::FileInfo::NestedCall::NestedCall(const Tokenizer *tokenizer, const Scope *scope, unsigned int argnr_, const Token *tok)
: :
id(getFunctionId(tokenizer, scope->function)), id(getFunctionId(tokenizer, scope->function)),
@ -331,34 +339,52 @@ static std::string replacestr(std::string s, const std::string &from, const std:
return s; return s;
} }
std::list<ErrorLogger::ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(const CTU::FileInfo::FunctionCall &functionCall, std::list<ErrorLogger::ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(InvalidValueType invalidValue,
const CTU::FileInfo::UnsafeUsage &unsafeUsage, const CTU::FileInfo::UnsafeUsage &unsafeUsage,
const std::map<std::string, std::list<CTU::FileInfo::NestedCall>> &nestedCallsMap, const std::map<std::string, std::list<CTU::FileInfo::NestedCall>> &nestedCallsMap,
const char info[]) const const char info[],
const FunctionCall * * const functionCallPtr) const
{ {
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
if (!findPath(functionCall, unsafeUsage, nestedCallsMap)) for (const FunctionCall &functionCall : functionCalls) {
if (invalidValue == CTU::FileInfo::InvalidValueType::null &&
(functionCall.valueType != ValueFlow::Value::ValueType::INT || functionCall.argvalue != 0)) {
continue;
}
if (invalidValue == CTU::FileInfo::InvalidValueType::uninit &&
functionCall.valueType != ValueFlow::Value::ValueType::UNINIT) {
continue;
}
if (!findPath(functionCall, unsafeUsage, nestedCallsMap))
continue;
if (functionCallPtr)
*functionCallPtr = &functionCall;
std::string value1;
if (functionCall.valueType == ValueFlow::Value::ValueType::INT)
value1 = "null";
else if (functionCall.valueType == ValueFlow::Value::ValueType::UNINIT)
value1 = "uninitialized";
ErrorLogger::ErrorMessage::FileLocation fileLoc1;
fileLoc1.setfile(functionCall.location.fileName);
fileLoc1.line = functionCall.location.linenr;
fileLoc1.setinfo("Calling function " + functionCall.functionName + ", " + MathLib::toString(functionCall.argnr) + getOrdinalText(functionCall.argnr) + " argument is " + value1);
ErrorLogger::ErrorMessage::FileLocation fileLoc2;
fileLoc2.setfile(unsafeUsage.location.fileName);
fileLoc2.line = unsafeUsage.location.linenr;
fileLoc2.setinfo(replacestr(info, "ARG", unsafeUsage.argumentName));
locationList.push_back(fileLoc1);
locationList.push_back(fileLoc2);
return locationList; return locationList;
}
std::string value1;
if (functionCall.valueType == ValueFlow::Value::ValueType::INT)
value1 = "null";
else if (functionCall.valueType == ValueFlow::Value::ValueType::UNINIT)
value1 = "uninitialized";
ErrorLogger::ErrorMessage::FileLocation fileLoc1;
fileLoc1.setfile(functionCall.location.fileName);
fileLoc1.line = functionCall.location.linenr;
fileLoc1.setinfo("Calling function " + functionCall.functionName + ", " + MathLib::toString(functionCall.argnr) + getOrdinalText(functionCall.argnr) + " argument is " + value1);
ErrorLogger::ErrorMessage::FileLocation fileLoc2;
fileLoc2.setfile(unsafeUsage.location.fileName);
fileLoc2.line = unsafeUsage.location.linenr;
fileLoc2.setinfo(replacestr(info, "ARG", unsafeUsage.argumentName));
locationList.push_back(fileLoc1);
locationList.push_back(fileLoc2);
return locationList; return locationList;
} }

View File

@ -91,12 +91,17 @@ namespace CTU {
void loadFromXml(const tinyxml2::XMLElement *xmlElement); void loadFromXml(const tinyxml2::XMLElement *xmlElement);
std::map<std::string, std::list<NestedCall>> getNestedCallsMap() const; std::map<std::string, std::list<NestedCall>> getNestedCallsMap() const;
std::list<ErrorLogger::ErrorMessage::FileLocation> getErrorPath(const FunctionCall &functionCall, enum InvalidValueType { null, uninit };
std::list<ErrorLogger::ErrorMessage::FileLocation> getErrorPath(InvalidValueType invalidValue,
const UnsafeUsage &unsafeUsage, const UnsafeUsage &unsafeUsage,
const std::map<std::string, std::list<NestedCall>> &nestedCallsMap, const std::map<std::string, std::list<NestedCall>> &nestedCallsMap,
const char info[]) const; const char info[],
const FunctionCall * * const functionCallPtr) const;
}; };
std::string toString(const std::list<FileInfo::UnsafeUsage> &unsafeUsage);
std::string getFunctionId(const Tokenizer *tokenizer, const Function *function); std::string getFunctionId(const Tokenizer *tokenizer, const Function *function);
/** @brief Parse current TU and extract file info */ /** @brief Parse current TU and extract file info */