CTU: Refactoring; getErrorPath
This commit is contained in:
parent
e39be48c92
commit
a6e227a73c
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
70
lib/ctu.cpp
70
lib/ctu.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue