summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-08-04 20:53:01 +0300
committerAndrei Karas <akaras@inbox.ru>2015-08-04 20:53:01 +0300
commite4c20844d13d4428466bb4bc3845b52c63985ca4 (patch)
treed14d81f20d82e99924bf0623c9e81bfc3e928ea3
parentb8242a03b51299f6b21d9916db10dca7fbaf8097 (diff)
downloadparanucker-e4c20844d13d4428466bb4bc3845b52c63985ca4.tar.gz
paranucker-e4c20844d13d4428466bb4bc3845b52c63985ca4.tar.bz2
paranucker-e4c20844d13d4428466bb4bc3845b52c63985ca4.tar.xz
paranucker-e4c20844d13d4428466bb4bc3845b52c63985ca4.zip
Add initial support for tracking 'nonnullpointer' attribute.
-rw-r--r--src/analysis/expression.cpp79
-rw-r--r--src/analysis/reports.cpp13
-rw-r--r--src/analysis/varitem.h14
3 files changed, 69 insertions, 37 deletions
diff --git a/src/analysis/expression.cpp b/src/analysis/expression.cpp
index fb7fa86..e3f3816 100644
--- a/src/analysis/expression.cpp
+++ b/src/analysis/expression.cpp
@@ -157,7 +157,7 @@ VarItem getComponentRefVariable(Node *node)
skipNop(fieldDecl->attribute)),
"nonnullpointer"))
{
- return str;
+ str.isNonNull = true;
}
IndirectRefNode *indirect = static_cast<IndirectRefNode*>(object);
Node *ref = skipNop(indirect->ref);
@@ -211,11 +211,12 @@ std::vector<VarItem> getComponentRefParts(Node *node)
{
FieldDeclNode *fieldDecl = static_cast<FieldDeclNode*>(field);
IndirectRefNode *indirect = static_cast<IndirectRefNode*>(object);
+ bool isNonNull(false);
if (findTreeListPurpose(static_cast<TreeListNode*>(
skipNop(fieldDecl->attribute)),
"nonnullpointer"))
{
- return str;
+ isNonNull = true;
}
Node *ref = skipNop(indirect->ref);
if (ref && !isValidVar(ref->label))
@@ -226,14 +227,14 @@ std::vector<VarItem> getComponentRefParts(Node *node)
if (skipNop(parmDecl->declType) == nullptr ||
skipNop(parmDecl->declType) == POINTER_TYPE)
{
- str.push_back(VarItem(ref->label));
+ str.push_back(VarItem(ref->label, isNonNull));
}
}
if (ref == VAR_DECL)
{
VarDeclNode *varDecl = static_cast<VarDeclNode*>(ref);
if (varDecl->varType == POINTER_TYPE)
- str.push_back(VarItem(ref->label));
+ str.push_back(VarItem(ref->label, isNonNull));
}
if (ref == PARM_DECL || ref == VAR_DECL)
{
@@ -247,7 +248,7 @@ std::vector<VarItem> getComponentRefParts(Node *node)
}
if (!isValidVar(field->label))
return str;
- str.push_back(VarItem(std::string(ref->label).append("->").append(field->label)));
+ str.push_back(VarItem(std::string(ref->label).append("->").append(field->label), isNonNull));
}
}
}
@@ -268,13 +269,14 @@ std::vector<VarItem> getComponentRefLeftParts(Node *node)
field == FIELD_DECL)
{
FieldDeclNode *fieldDecl = static_cast<FieldDeclNode*>(field);
+ bool isNonNull(false);
// if (fieldDecl->fieldType != POINTER_TYPE)
// return str;
if (findTreeListPurpose(static_cast<TreeListNode*>(
skipNop(fieldDecl->attribute)),
"nonnullpointer"))
{
- return str;
+ isNonNull = true;
}
IndirectRefNode *indirect = static_cast<IndirectRefNode*>(object);
Node *ref = skipNop(indirect->ref);
@@ -282,7 +284,7 @@ std::vector<VarItem> getComponentRefLeftParts(Node *node)
return str;
if (ref == PARM_DECL || ref == VAR_DECL)
{
- str.push_back(VarItem(ref->label));
+ str.push_back(VarItem(ref->label, isNonNull));
}
}
}
@@ -308,7 +310,7 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo)
if (skipNop(comp->object) == INDIRECT_REF)
arg0 = skipNop(comp->object);
- if (arg0 == INDIRECT_REF)
+ if (arg0 == INDIRECT_REF && !var1.isNonNull)
{
// var2 not found in known checking pointer
reportParmDeclNullPointer(node,
@@ -318,16 +320,19 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo)
}
if (arg == INDIRECT_REF)
{
- // var2 not found in known checking pointer
- reportParmDeclNullPointer(node,
- static_cast<IndirectRefNode*>(arg)->ref,
- wi);
-
- if (!var1.empty() &&
- isNotIn(var2.name, wi.needCheckNullVars) &&
- isNotIn(var2.name, wi.knownVars))
+ if (!var1.isNonNull)
{
- removeVar(wo, var1.name);
+ // var2 not found in known checking pointer
+ reportParmDeclNullPointer(node,
+ static_cast<IndirectRefNode*>(arg)->ref,
+ wi);
+
+ if (!var1.empty() &&
+ isNotIn(var2.name, wi.needCheckNullVars) &&
+ isNotIn(var2.name, wi.knownVars))
+ {
+ removeVar(wo, var1.name);
+ }
}
}
else if (!var1.empty())
@@ -345,7 +350,7 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo)
bool handled(false);
handled = handleSetVarToFunction(var1, arg, arg1, wo);
// have var1 only (var1 = UNKNOWN)
- if (!handled)
+ if (!var1.isNonNull && !handled)
removeVar(wo, var1.name);
}
else
@@ -355,7 +360,8 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo)
addLinkedVar(wo, var2.name, var1.name);
}
// var2 not found in known checking pointer
- else if (isNotIn(var2.name, wi.needCheckNullVars) &&
+ else if (!var1.isNonNull &&
+ isNotIn(var2.name, wi.needCheckNullVars) &&
isNotIn(var2.name, wi.knownVars))
{
removeVar(wo, var1.name);
@@ -377,6 +383,7 @@ void analysePointerPlusExpr(PointerPlusExprNode *node,
if (node->args.empty() || checkCommand(FindArgs))
return;
+ VarItem var = getVariableName(node->args[0]);
reportParmDeclNullPointer(node, node->args[0], wi);
}
@@ -403,10 +410,11 @@ void analyseAddrExpr(AddrExprNode *node,
}
}
+ VarItem var = getVariableName(node->args[0]);
if (skipNop(node->args[0]) == VAR_DECL)
{
// do not report if found &ptr
- if (!getVariableName(node->args[0]).empty())
+ if (!var.empty())
return;
}
reportParmDeclNullPointer(node, node->args[0], wi);
@@ -927,6 +935,8 @@ void analyseCallExpr(CallExprNode *node, const WalkItem &wi, WalkItem &wo)
{
wo2 = wo;
Node *node2 = skipNop(it);
+
+ VarItem var = getVariableName(node2);
if (enableCheck)
{
reportParmDeclNullPointer(node, node2, wi);
@@ -952,6 +962,7 @@ void analyseCleanupPointExpr(CleanupPointExprNode* node, const WalkItem &wi, Wal
{
wo2 = wo;
Node *node2 = skipNop(it);
+ VarItem var = getVariableName(node2);
reportParmDeclNullPointer(node, node2, wi);
walkTree(node2, wi, wo2);
Log::dumpWI(node, "wo arg ", wo2);
@@ -985,10 +996,13 @@ bool handleSetVarToFunctionBack(const VarItem &var,
if (wo2.isNum)
{
- if (wo2.num == 0)
- addNullVar(wo, var.name);
- else
- addNonNullVar(wo, var.name);
+ if (!var.isNonNull)
+ {
+ if (wo2.num == 0)
+ addNullVar(wo, var.name);
+ else
+ addNonNullVar(wo, var.name);
+ }
return true;
}
return false;
@@ -999,6 +1013,8 @@ bool handleSetVarToFunction(const VarItem &var,
Node *node2,
WalkItem &wo)
{
+ if (var.isNonNull)
+ return false;
node1 = skipNop(node1);
node2 = skipNop(node2);
@@ -1010,7 +1026,7 @@ bool handleSetVarToFunction(const VarItem &var,
if (node2 == nullptr)
{ // type *var;
- if (isNotIn(var.name, wo.knownVars))
+ if (!var.isNonNull && isNotIn(var.name, wo.knownVars))
addUnknownVar(wo, var.name);
return true;
}
@@ -1021,10 +1037,13 @@ bool handleSetVarToFunction(const VarItem &var,
if (!addr->args.empty() && skipNop(addr->args[0]) == VAR_DECL)
{
VarDeclNode *varDecl = static_cast<VarDeclNode*>(skipNop(addr->args[0]));
- if (skipNop(varDecl->varType) != POINTER_TYPE)
- addNonNullVar(wo, var.name);
- else
- addUnknownVar(wo, var.name);
+ if (!var.isNonNull)
+ {
+ if (skipNop(varDecl->varType) != POINTER_TYPE)
+ addNonNullVar(wo, var.name);
+ else
+ addUnknownVar(wo, var.name);
+ }
return true;
}
}
@@ -1128,7 +1147,7 @@ void handleSetVar(Node *node1,
{
if (isIn(var2.name, wi.knownVars))
addLinkedVar(wo, var2.name, var1.name);
- else
+ else if (!var1.isNonNull)
addUnknownVar(wo, var1.name);
}
}
diff --git a/src/analysis/reports.cpp b/src/analysis/reports.cpp
index 03ba641..7e7ceb3 100644
--- a/src/analysis/reports.cpp
+++ b/src/analysis/reports.cpp
@@ -96,8 +96,9 @@ void reportParmDeclNullPointer(Node *mainNode,
auto vars = getComponentRefParts(node);
FOR_EACH (var, vars)
{
- if (isIn(var.name, wi.needCheckNullVars) ||
- isNotIn(var.name, wi.knownVars))
+ if (!var.isNonNull &&
+ (isIn(var.name, wi.needCheckNullVars) ||
+ isNotIn(var.name, wi.knownVars)))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
@@ -121,7 +122,8 @@ void reportParmDeclLeftNullPointer(Node *mainNode,
auto vars = getComponentRefLeftParts(node);
FOR_EACH (var, vars)
{
- if (isIn(var.name, wi.needCheckNullVars))
+ if (!var.isNonNull &&
+ isIn(var.name, wi.needCheckNullVars))
{
Log::warn(findBackLocation(mainNode),
"Using field '%s' without checking for null pointer",
@@ -145,7 +147,8 @@ void reportComponentRefNullPointer(Node *mainNode,
auto vars = getComponentRefParts(node);
FOR_EACH (var, vars)
{
- if (isIn(var.name, wi.needCheckNullVars))
+ if (!var.isNonNull &&
+ isIn(var.name, wi.needCheckNullVars))
{
Log::warn(findBackLocation(mainNode),
"Using field '%s' without checking for null pointer",
@@ -187,7 +190,7 @@ void reportParmDeclAttrNullPointer(Node *mainNode,
else if (node == COMPONENT_REF)
{
VarItem var = getComponentRefVariable(node);
- if (isIn(var.name, wi.needCheckNullVars))
+ if (!var.isNonNull && isIn(var.name, wi.needCheckNullVars))
reportPossibleNullPointer(mainNode, node->label);
}
}
diff --git a/src/analysis/varitem.h b/src/analysis/varitem.h
index 1fe6b20..cbc7441 100644
--- a/src/analysis/varitem.h
+++ b/src/analysis/varitem.h
@@ -25,12 +25,21 @@
struct VarItem
{
VarItem() :
- name()
+ name(),
+ isNonNull(false)
{
}
VarItem(const std::string &name0) :
- name(name0)
+ name(name0),
+ isNonNull(false)
+ {
+ }
+
+ VarItem(const std::string &name0,
+ const bool isNonNull0) :
+ name(name0),
+ isNonNull(isNonNull0)
{
}
@@ -41,6 +50,7 @@ struct VarItem
{ return name.size(); }
std::string name;
+ bool isNonNull;
};