diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-07-01 22:06:13 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-07-01 23:38:38 +0300 |
commit | 012416297ee90f324f23d59accf5d59736d57c23 (patch) | |
tree | 2ffe4caaa97f55b46ad17e0d7ef1ec81ce6c2161 /src/analysis/checks.cpp | |
parent | 1f8411373577372f1b4c969a7f1c87f8f8354107 (diff) | |
download | paranucker-012416297ee90f324f23d59accf5d59736d57c23.tar.gz paranucker-012416297ee90f324f23d59accf5d59736d57c23.tar.bz2 paranucker-012416297ee90f324f23d59accf5d59736d57c23.tar.xz paranucker-012416297ee90f324f23d59accf5d59736d57c23.zip |
Add way for check internall collections by pseudo function call from code.
Diffstat (limited to 'src/analysis/checks.cpp')
-rw-r--r-- | src/analysis/checks.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/analysis/checks.cpp b/src/analysis/checks.cpp new file mode 100644 index 0000000..15f15bd --- /dev/null +++ b/src/analysis/checks.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2015 Andrei Karas + * + * This file is part of Paranoid null checker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "analysis/checks.h" + +#include "logger.h" + +#include "analysis/analysis.h" +#include "analysis/expression.h" +#include "analysis/reports.h" +#include "analysis/walkitem.h" + +#include "nodes/cst/string_cst.h" + +#include "nodes/expr/addr_expr.h" +#include "nodes/expr/call_expr.h" + +#include <string> + +#include "localconsts.h" + +namespace Analysis +{ + +void getCallFunctionStringArgs(CallExprNode *node, + std::vector<std::string> &arr) +{ + FOR_EACH (it, node->args) + { + Node *arg = skipNop(it); + if (arg == ADDR_EXPR) + { + AddrExprNode *addr = static_cast<AddrExprNode*>(arg); + if (!addr->args.empty() && addr->args[0] == STRING_CST) + { + arr.push_back(addr->args[0]->label); + } + } + } +} + +std::string mergeCollection(const std::set<std::string> &col) +{ + std::string str; + FOR_EACH(it, col) + { + str.append(it).append(","); + } + return str; +} + +void reportCollections(Node *node, + const std::string &name, + std::set<std::string> col1, + std::set<std::string> col2) +{ + std::string str1 = mergeCollection(col1); + std::string str2 = mergeCollection(col2); + reportCollectionsDifferent(node, name, str1, str2); +} + +void checkStateEqual(Node *node, + const std::string &name, + std::set<std::string> col1, + std::set<std::string> col2) +{ + FOR_EACH (it, col1) + { + if (isNotIn(it, col2)) + { + reportCollections(node, name, col1, col2); + return; + } + } + FOR_EACH (it, col2) + { + if (isNotIn(it, col1)) + { + reportCollections(node, name, col1, col2); + return; + } + } +} + +void checkStateIn(Node *node, + const std::string &name, + const std::set<std::string> &col1, + const std::set<std::string> &col2) +{ +} + +#define convertCollection(col) \ + if (name == #col) \ + { \ + return wi.col; \ + } + +std::set<std::string> getCollection(Node *node, + const std::string &name, + const WalkItem &wi) +{ + convertCollection(needCheckNullVars) + else convertCollection(knownVars) + else convertCollection(knownNullVars) + else convertCollection(knownNonNullVars) + else convertCollection(removeNullVarsAll) + else convertCollection(removeNullVars) + else convertCollection(addNullVars) + else convertCollection(checkedNullVars) + else convertCollection(checkedNonNullVars) + else + { + reportWrongCheck(node); + return std::set<std::string>(); + } +} + +std::set<std::string> splitArgs(std::string args) +{ + std::set<std::string> tokens; + size_t idx = 0; + while ((idx = args.find(" ")) != std::string::npos) + { + tokens.insert(args.substr(0, idx)); + args = args.substr(idx + 1); + } + if (!args.empty()) + tokens.insert(args); + return tokens; +} + +void checkState(CallExprNode *node, const WalkItem &wi) +{ + if (!node) + return; + + std::vector<std::string> args; + getCallFunctionStringArgs(node, args); + if (args.size() != 3) + { + reportWrongCheck(node); + return; + } + std::string name = args[1]; + std::set<std::string> col1 = getCollection(node, name, wi); + std::set<std::string> col2 = splitArgs(args[2]); + if (args[0] == "=") + checkStateEqual(node, name, col1, col2); + else if (args[1] == "in") + checkStateIn(node, name, col1, col2); + else + reportWrongCheck(node); +} + +} |