diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-07-23 02:14:15 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-07-23 02:14:15 +0300 |
commit | eff039b810786f96ed8f0bade95ff07a7c4e15dd (patch) | |
tree | fa6f647e298446f0a9744b363a5e3d2d73eb76b6 | |
parent | d334657133cb123b79e5998c151b5285fc204018 (diff) | |
download | paranucker-eff039b810786f96ed8f0bade95ff07a7c4e15dd.tar.gz paranucker-eff039b810786f96ed8f0bade95ff07a7c4e15dd.tar.bz2 paranucker-eff039b810786f96ed8f0bade95ff07a7c4e15dd.tar.xz paranucker-eff039b810786f96ed8f0bade95ff07a7c4e15dd.zip |
Remove null checks from COMPONENT_REF node. But add check in different parent nodes.
-rw-r--r-- | src/analysis/analysis.cpp | 4 | ||||
-rw-r--r-- | src/analysis/expression.cpp | 95 | ||||
-rw-r--r-- | src/analysis/expression.h | 6 | ||||
-rw-r--r-- | src/analysis/ref.cpp | 15 | ||||
-rw-r--r-- | src/analysis/ref.h | 2 | ||||
-rw-r--r-- | src/analysis/reports.cpp | 73 | ||||
-rw-r--r-- | src/analysis/reports.h | 8 | ||||
-rw-r--r-- | src/analysis/statement.cpp | 2 |
8 files changed, 195 insertions, 10 deletions
diff --git a/src/analysis/analysis.cpp b/src/analysis/analysis.cpp index 32c0170..50f9211 100644 --- a/src/analysis/analysis.cpp +++ b/src/analysis/analysis.cpp @@ -53,6 +53,7 @@ #include "nodes/expr/truthor_expr.h" #include "nodes/expr/truthorif_expr.h" +#include "nodes/ref/array_ref.h" #include "nodes/ref/component_ref.h" #include "nodes/stmt/break_stmt.h" @@ -291,6 +292,9 @@ void analyseNode(Node *node, const WalkItem &wi, WalkItem &wo) case CONTINUE_STMT: analyseContinueStmt(static_cast<ContinueStmtNode*>(node), wi2, wo); break; + case ARRAY_REF: + analyseArrayRef(static_cast<ArrayRefNode*>(node), wi2, wo); + break; case COMPONENT_REF: analyseComponentRef(static_cast<ComponentRefNode*>(node), wi2, wo); break; diff --git a/src/analysis/expression.cpp b/src/analysis/expression.cpp index 3877d68..7370a57 100644 --- a/src/analysis/expression.cpp +++ b/src/analysis/expression.cpp @@ -60,6 +60,7 @@ #include "nodes/ref/indirect_ref.h" #include "nodes/ref/objtype_ref.h" +#include "nodes/type/array_type.h" #include "nodes/type/method_type.h" #include <set> @@ -141,6 +142,78 @@ std::string getComponentRefVariable(Node *node) return str; } +std::vector<std::string> getComponentRefParts(Node *node) +{ + std::vector<std::string> str; + ComponentRefNode *const comp = static_cast<ComponentRefNode*>(skipNop(node)); + if (comp && + comp->object && + comp->field) + { + Node *object = skipNop(comp->object); + Node *field = skipNop(comp->field); + if (object == INDIRECT_REF && + field == FIELD_DECL) + { + FieldDeclNode *fieldDecl = static_cast<FieldDeclNode*>(field); + IndirectRefNode *indirect = static_cast<IndirectRefNode*>(object); + Node *ref = skipNop(indirect->ref); + if (ref == PARM_DECL) + { + ParmDeclNode *parmDecl = static_cast<ParmDeclNode*>(ref); + if (parmDecl->declType == POINTER_TYPE) + str.push_back(ref->label); + } + if (ref == VAR_DECL) + { + VarDeclNode *varDecl = static_cast<VarDeclNode*>(ref); + if (varDecl->varType == POINTER_TYPE) + str.push_back(ref->label); + } + if (ref == PARM_DECL || ref == VAR_DECL) + { + if (skipNop(fieldDecl->fieldType) != POINTER_TYPE) + { + if (skipNop(fieldDecl->fieldType) != ARRAY_TYPE) + return str; + ArrayTypeNode *arr = static_cast<ArrayTypeNode*>(skipNop(fieldDecl->fieldType)); + if (arr->elementType != POINTER_TYPE) + return str; + } + str.push_back(std::string(ref->label).append("->").append(field->label)); + } + } + } + return str; +} + +std::vector<std::string> getComponentRefLeftParts(Node *node) +{ + std::vector<std::string> str; + ComponentRefNode *const comp = static_cast<ComponentRefNode*>(skipNop(node)); + if (comp && + comp->object && + comp->field) + { + Node *object = skipNop(comp->object); + Node *field = skipNop(comp->field); + if (object == INDIRECT_REF && + field == FIELD_DECL) + { +// FieldDeclNode *fieldDecl = static_cast<FieldDeclNode*>(field); +// if (fieldDecl->fieldType != POINTER_TYPE) +// return str; + IndirectRefNode *indirect = static_cast<IndirectRefNode*>(object); + Node *ref = skipNop(indirect->ref); + if (ref == PARM_DECL || ref == VAR_DECL) + { + str.push_back(ref->label); + } + } + } + return str; +} + void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo) { // need atleast one arg for check @@ -159,15 +232,24 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo) ComponentRefNode *comp = static_cast<ComponentRefNode*>(arg); if (skipNop(comp->object) == INDIRECT_REF) arg0 = skipNop(comp->object); + + if (arg0 == INDIRECT_REF) + { + // var2 not found in known checking pointer + reportParmDeclNullPointer(node, + static_cast<IndirectRefNode*>(arg0)->ref, + wi); + } } - if (arg0 == INDIRECT_REF) + if (arg == INDIRECT_REF) { // var2 not found in known checking pointer reportParmDeclNullPointer(node, - static_cast<IndirectRefNode*>(arg0)->ref, + static_cast<IndirectRefNode*>(arg)->ref, wi); - if (isNotIn(var2, wi.needCheckNullVars) && + if (!var1.empty() && + isNotIn(var2, wi.needCheckNullVars) && isNotIn(var2, wi.knownVars)) { removeVar(wo, var1); @@ -263,6 +345,9 @@ void analyseNeExpr(NeExprNode *node, const WalkItem &wi, WalkItem &wo) // INTEGER_CST? Node *node2 = skipNop(node->args[1]); + reportParmDeclLeftNullPointer(node, node1, wi); + reportParmDeclLeftNullPointer(node, node2, wi); + std::string var = getVariableName(node1); // if (var != 0) if (!var.empty() && @@ -375,6 +460,10 @@ void analyseEqExpr(EqExprNode *node, const WalkItem &wi, WalkItem &wo) Node *node1 = skipNop(node->args[0]); // INTEGER_CST? Node *node2 = skipNop(node->args[1]); + + reportParmDeclLeftNullPointer(node, node1, wi); + reportParmDeclLeftNullPointer(node, node2, wi); + std::string var = getVariableName(node1); // if (var == 0) if (!var.empty() && diff --git a/src/analysis/expression.h b/src/analysis/expression.h index 9c42bd2..602a9ae 100644 --- a/src/analysis/expression.h +++ b/src/analysis/expression.h @@ -44,6 +44,8 @@ struct TruthOrExprNode; struct TruthOrIfExprNode; struct WalkItem; +#include <vector> + namespace Analysis { void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo); @@ -95,6 +97,10 @@ namespace Analysis std::string getComponentRefVariable(Node *node); + std::vector<std::string> getComponentRefParts(Node *node); + + std::vector<std::string> getComponentRefLeftParts(Node *node); + bool handleSetVarToFunction(const std::string &var, Node *node1, Node *node2, diff --git a/src/analysis/ref.cpp b/src/analysis/ref.cpp index 4c8a4be..2391fa3 100644 --- a/src/analysis/ref.cpp +++ b/src/analysis/ref.cpp @@ -30,6 +30,7 @@ #include "nodes/expr/modify_expr.h" #include "nodes/expr/pointerplus_expr.h" +#include "nodes/ref/array_ref.h" #include "nodes/ref/component_ref.h" #include "nodes/ref/indirect_ref.h" @@ -59,4 +60,18 @@ void analyseComponentRef(ComponentRefNode *node, */ } +void analyseArrayRef(ArrayRefNode *node, + const WalkItem &wi, + WalkItem &wo A_UNUSED) +{ + // need atleast one arg for check + if (node->args.empty() || checkCommand(FindArgs)) + return; + + FOR_EACH(it, node->args) + { + reportParmDeclNullPointer(node, it, wi); + } +} + } diff --git a/src/analysis/ref.h b/src/analysis/ref.h index ff245cc..608d033 100644 --- a/src/analysis/ref.h +++ b/src/analysis/ref.h @@ -22,12 +22,14 @@ #include "includes.h" +struct ArrayRefNode; struct ComponentRefNode; struct WalkItem; namespace Analysis { void analyseComponentRef(ComponentRefNode *node, const WalkItem &wi, WalkItem &wo); + void analyseArrayRef(ArrayRefNode *node, const WalkItem &wi, WalkItem &wo); } #endif // ANALYSIS_REF_H diff --git a/src/analysis/reports.cpp b/src/analysis/reports.cpp index af5806b..733171a 100644 --- a/src/analysis/reports.cpp +++ b/src/analysis/reports.cpp @@ -28,6 +28,9 @@ #include "nodes/base/node.h" +#include "nodes/decl/parm_decl.h" +#include "nodes/decl/var_decl.h" + #include "localconsts.h" namespace Analysis @@ -66,7 +69,9 @@ void reportParmDeclNullPointer(Node *mainNode, { if (node == PARM_DECL) { - if (isIn(node->label, wi.needCheckNullVars)) + ParmDeclNode *parmDecl = static_cast<ParmDeclNode*>(node); + if (parmDecl->declType == POINTER_TYPE && + isIn(node->label, wi.needCheckNullVars)) { Log::warn(findBackLocation(mainNode), "Using parameter '%s' without checking for null pointer", @@ -75,7 +80,9 @@ void reportParmDeclNullPointer(Node *mainNode, } else if (node == VAR_DECL) { - if (isIn(node->label, wi.needCheckNullVars)) + VarDeclNode *varDecl = static_cast<VarDeclNode*>(node); + if (varDecl->varType == POINTER_TYPE && + isIn(node->label, wi.needCheckNullVars)) { Log::warn(findBackLocation(mainNode), "Using variable '%s' without checking for null pointer", @@ -85,12 +92,64 @@ void reportParmDeclNullPointer(Node *mainNode, } else if (node == COMPONENT_REF) { - std::string var = getComponentRefVariable(node); - if (isIn(var, wi.needCheckNullVars)) + auto vars = getComponentRefParts(node); + FOR_EACH (var, vars) { - Log::warn(findBackLocation(mainNode), - "Using field '%s' without checking for null pointer", - var); + if (isIn(var, wi.needCheckNullVars) || + isNotIn(var, wi.knownVars)) + { + Log::warn(findBackLocation(mainNode), + "Using variable '%s' without checking for null pointer", + var); + } + } + } + } +} + +// report about null pointer if need for node +void reportParmDeclLeftNullPointer(Node *mainNode, + Node *node, + const WalkItem &wi) +{ + node = skipNop(node); + if (node) + { + if (node == COMPONENT_REF) + { + auto vars = getComponentRefLeftParts(node); + FOR_EACH (var, vars) + { + if (isIn(var, wi.needCheckNullVars)) + { + Log::warn(findBackLocation(mainNode), + "Using field '%s' without checking for null pointer", + var); + } + } + } + } +} + +// report about null pointer if need for node +void reportComponentRefNullPointer(Node *mainNode, + Node *node, + const WalkItem &wi) +{ + node = skipNop(node); + if (node) + { + if (node == COMPONENT_REF) + { + auto vars = getComponentRefParts(node); + FOR_EACH (var, vars) + { + if (isIn(var, wi.needCheckNullVars)) + { + Log::warn(findBackLocation(mainNode), + "Using field '%s' without checking for null pointer", + var); + } } } } diff --git a/src/analysis/reports.h b/src/analysis/reports.h index 4278ee4..7f65fb8 100644 --- a/src/analysis/reports.h +++ b/src/analysis/reports.h @@ -34,6 +34,14 @@ namespace Analysis Node *node, const WalkItem &wi); + void reportParmDeclLeftNullPointer(Node *mainNode, + Node *node, + const WalkItem &wi); + + void reportComponentRefNullPointer(Node *mainNode, + Node *node, + const WalkItem &wi); + void reportParmDeclAttrNullPointer(Node *mainNode, Node *node, const WalkItem &wi); diff --git a/src/analysis/statement.cpp b/src/analysis/statement.cpp index 5e6ea7a..a5aba2d 100644 --- a/src/analysis/statement.cpp +++ b/src/analysis/statement.cpp @@ -79,6 +79,7 @@ void analyseCondition(Node *node, reportParmDeclNullPointer(node, thenNode, wi2); + reportParmDeclLeftNullPointer(node, thenNode, wi2); walkTree(thenNode, wi2, wo2); Log::dumpWI(node, "wo2 then ", wo2); @@ -98,6 +99,7 @@ void analyseCondition(Node *node, reportParmDeclNullPointer(node, elseNode, wi3); + reportParmDeclLeftNullPointer(node, elseNode, wi3); walkTree(elseNode, wi3, wo3); Log::dumpWI(node, "wo3 else ", wo3); |