同步操作将从 Gitee 极速下载/Cppcheck 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#include "programmemory.h"#include "token.h"#include "astutils.h"#include "symboldatabase.h"#include <algorithm>#include <cassert>void ProgramMemory::setValue(nonneg int varid, const ValueFlow::Value &value){values[varid] = value;}bool ProgramMemory::getIntValue(nonneg int varid, MathLib::bigint* result) const{const ProgramMemory::Map::const_iterator it = values.find(varid);const bool found = it != values.end() && it->second.isIntValue();if (found)*result = it->second.intvalue;return found;}void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value){values[varid] = ValueFlow::Value(value);}bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const{const ProgramMemory::Map::const_iterator it = values.find(varid);const bool found = it != values.end() && it->second.isTokValue();if (found)*result = it->second.tokvalue;return found;}void ProgramMemory::setUnknown(nonneg int varid){values[varid].valueType = ValueFlow::Value::ValueType::UNINIT;}bool ProgramMemory::hasValue(nonneg int varid){return values.find(varid) != values.end();}void ProgramMemory::swap(ProgramMemory &pm){values.swap(pm.values);}void ProgramMemory::clear(){values.clear();}bool ProgramMemory::empty() const{return values.empty();}void ProgramMemory::replace(const ProgramMemory &pm){for (auto&& p:pm.values)values[p.first] = p.second;}void ProgramMemory::insert(const ProgramMemory &pm){for (auto&& p:pm.values)values.insert(p);}bool conditionIsFalse(const Token *condition, const ProgramMemory &programMemory){if (!condition)return false;if (condition->str() == "&&") {return conditionIsFalse(condition->astOperand1(), programMemory) ||conditionIsFalse(condition->astOperand2(), programMemory);}ProgramMemory progmem(programMemory);MathLib::bigint result = 0;bool error = false;execute(condition, &progmem, &result, &error);return !error && result == 0;}bool conditionIsTrue(const Token *condition, const ProgramMemory &programMemory){if (!condition)return false;if (condition->str() == "||") {return conditionIsTrue(condition->astOperand1(), programMemory) ||conditionIsTrue(condition->astOperand2(), programMemory);}ProgramMemory progmem(programMemory);bool error = false;MathLib::bigint result = 0;execute(condition, &progmem, &result, &error);return !error && result == 1;}static void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Token* endTok, const Settings* settings, bool then){if (Token::Match(tok, "==|>=|<=|<|>|!=")) {if (then && !Token::Match(tok, "==|>=|<="))return;if (!then && !Token::Match(tok, "<|>|!="))return;ValueFlow::Value truevalue;ValueFlow::Value falsevalue;const Token* vartok = parseCompareInt(tok, truevalue, falsevalue);if (!vartok)return;if (vartok->varId() == 0)return;if (!truevalue.isIntValue())return;if (endTok && isVariableChanged(tok->next(), endTok, vartok->varId(), false, settings, true))return;pm.setIntValue(vartok->varId(), then ? truevalue.intvalue : falsevalue.intvalue);} else if (Token::Match(tok, "%var%")) {if (tok->varId() == 0)return;if (then && !astIsPointer(tok) && !astIsBool(tok))return;if (endTok && isVariableChanged(tok->next(), endTok, tok->varId(), false, settings, true))return;pm.setIntValue(tok->varId(), then);} else if (Token::simpleMatch(tok, "!")) {programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, !then);} else if (then && Token::simpleMatch(tok, "&&")) {programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);programMemoryParseCondition(pm, tok->astOperand2(), endTok, settings, then);} else if (!then && Token::simpleMatch(tok, "||")) {programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);programMemoryParseCondition(pm, tok->astOperand2(), endTok, settings, then);}}static void fillProgramMemoryFromConditions(ProgramMemory& pm, const Scope* scope, const Token* endTok, const Settings* settings){if (!scope)return;if (!scope->isLocal())return;assert(scope != scope->nestedIn);fillProgramMemoryFromConditions(pm, scope->nestedIn, endTok, settings);if (scope->type == Scope::eIf || scope->type == Scope::eWhile || scope->type == Scope::eElse) {const Token * bodyStart = scope->bodyStart;if (scope->type == Scope::eElse) {if (!Token::simpleMatch(bodyStart->tokAt(-2), "} else {"))return;bodyStart = bodyStart->linkAt(-2);}const Token * condEndTok = bodyStart->previous();if (!Token::simpleMatch(condEndTok, ") {"))return;const Token * condStartTok = condEndTok->link();if (!condStartTok)return;if (!Token::Match(condStartTok->previous(), "if|while ("))return;const Token * condTok = condStartTok->astOperand2();programMemoryParseCondition(pm, condTok, endTok, settings, scope->type != Scope::eElse);}}static void fillProgramMemoryFromConditions(ProgramMemory& pm, const Token* tok, const Settings* settings){fillProgramMemoryFromConditions(pm, tok->scope(), tok, settings);}static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok, const ProgramMemory& state, ProgramMemory::Map vars){int indentlevel = 0;for (const Token *tok2 = tok; tok2; tok2 = tok2->previous()) {bool setvar = false;if (Token::Match(tok2, "[;{}] %var% = %var% ;")) {for (auto&& p:vars) {if (p.first != tok2->next()->varId())continue;const Token *vartok = tok2->tokAt(3);pm.setValue(vartok->varId(), p.second);setvar = true;}}if (!setvar && (Token::Match(tok2, ";|{|}|%type% %var% =") ||Token::Match(tok2, "[;{}] const| %type% %var% ("))) {const Token *vartok = tok2->next();while (vartok->next()->isName())vartok = vartok->next();if (!pm.hasValue(vartok->varId())) {MathLib::bigint result = 0;bool error = false;execute(vartok->next()->astOperand2(), &pm, &result, &error);if (!error)pm.setIntValue(vartok->varId(), result);elsepm.setUnknown(vartok->varId());}} else if (!setvar && Token::Match(tok2, "%var% !!=") && isVariableChanged(tok2, 0, nullptr, true)) {const Token *vartok = tok2;if (!pm.hasValue(vartok->varId()))pm.setUnknown(vartok->varId());}if (tok2->str() == "{") {if (indentlevel <= 0)break;--indentlevel;}if (tok2->str() == "}") {const Token *cond = tok2->link();cond = Token::simpleMatch(cond->previous(), ") {") ? cond->linkAt(-1) : nullptr;if (cond && conditionIsFalse(cond->astOperand2(), state))tok2 = cond->previous();else if (cond && conditionIsTrue(cond->astOperand2(), state)) {++indentlevel;continue;} elsebreak;}}}static void removeModifiedVars(ProgramMemory& pm, const Token* tok, const Token* origin){for (auto i = pm.values.begin(), last = pm.values.end(); i != last;) {if (isVariableChanged(origin, tok, i->first, false, nullptr, true)) {i = pm.values.erase(i);} else {++i;}}}static ProgramMemory getInitialProgramState(const Token* tok,const Token* origin,const ProgramMemory::Map& vars = ProgramMemory::Map {}){ProgramMemory pm;if (origin) {fillProgramMemoryFromConditions(pm, origin, nullptr);const ProgramMemory state = pm;fillProgramMemoryFromAssignments(pm, tok, state, vars);removeModifiedVars(pm, tok, origin);}return pm;}void ProgramMemoryState::insert(const ProgramMemory &pm, const Token* origin){if (origin)for (auto&& p:pm.values)origins.insert(std::make_pair(p.first, origin));state.insert(pm);}void ProgramMemoryState::replace(const ProgramMemory &pm, const Token* origin){if (origin)for (auto&& p:pm.values)origins[p.first] = origin;state.replace(pm);}void ProgramMemoryState::addState(const Token* tok, const ProgramMemory::Map& vars){ProgramMemory pm;fillProgramMemoryFromConditions(pm, tok, nullptr);ProgramMemory local;for (const auto& p:vars) {nonneg int varid = p.first;const ValueFlow::Value &value = p.second;pm.setValue(varid, value);if (value.varId)pm.setIntValue(value.varId, value.varvalue);}local = pm;fillProgramMemoryFromAssignments(pm, tok, local, vars);replace(pm, tok);}void ProgramMemoryState::assume(const Token* tok, bool b){ProgramMemory pm = state;programMemoryParseCondition(pm, tok, nullptr, nullptr, b);insert(pm, tok);}void ProgramMemoryState::removeModifiedVars(const Token* tok){for (auto i = state.values.begin(), last = state.values.end(); i != last;) {if (isVariableChanged(origins[i->first], tok, i->first, false, nullptr, true)) {origins.erase(i->first);i = state.values.erase(i);} else {++i;}}}ProgramMemory ProgramMemoryState::get(const Token *tok, const ProgramMemory::Map& vars) const{ProgramMemoryState local = *this;local.addState(tok, vars);local.removeModifiedVars(tok);return local.state;}ProgramMemory getProgramMemory(const Token *tok, const ProgramMemory::Map& vars){ProgramMemory programMemory;for (const auto& p:vars) {const ValueFlow::Value &value = p.second;programMemory.replace(getInitialProgramState(tok, value.tokvalue));programMemory.replace(getInitialProgramState(tok, value.condition));}fillProgramMemoryFromConditions(programMemory, tok, nullptr);ProgramMemory state;for (const auto& p:vars) {nonneg int varid = p.first;const ValueFlow::Value &value = p.second;programMemory.setValue(varid, value);if (value.varId)programMemory.setIntValue(value.varId, value.varvalue);}state = programMemory;fillProgramMemoryFromAssignments(programMemory, tok, state, vars);return programMemory;}ProgramMemory getProgramMemory(const Token *tok, nonneg int varid, const ValueFlow::Value &value){ProgramMemory programMemory;programMemory.replace(getInitialProgramState(tok, value.tokvalue));programMemory.replace(getInitialProgramState(tok, value.condition));fillProgramMemoryFromConditions(programMemory, tok, nullptr);programMemory.setValue(varid, value);if (value.varId)programMemory.setIntValue(value.varId, value.varvalue);const ProgramMemory state = programMemory;fillProgramMemoryFromAssignments(programMemory, tok, state, {{varid, value}});return programMemory;}void execute(const Token *expr,ProgramMemory * const programMemory,MathLib::bigint *result,bool *error){if (!expr)*error = true;else if (expr->hasKnownIntValue()) {*result = expr->values().front().intvalue;}else if (expr->isNumber()) {*result = MathLib::toLongNumber(expr->str());if (MathLib::isFloat(expr->str()))*error = true;}else if (expr->varId() > 0) {if (!programMemory->getIntValue(expr->varId(), result))*error = true;}else if (expr->isComparisonOp()) {MathLib::bigint result1(0), result2(0);execute(expr->astOperand1(), programMemory, &result1, error);execute(expr->astOperand2(), programMemory, &result2, error);if (expr->str() == "<")*result = result1 < result2;else if (expr->str() == "<=")*result = result1 <= result2;else if (expr->str() == ">")*result = result1 > result2;else if (expr->str() == ">=")*result = result1 >= result2;else if (expr->str() == "==")*result = result1 == result2;else if (expr->str() == "!=")*result = result1 != result2;}else if (expr->isAssignmentOp()) {execute(expr->astOperand2(), programMemory, result, error);if (!expr->astOperand1() || !expr->astOperand1()->varId())*error = true;if (*error)return;if (expr->str() == "=") {programMemory->setIntValue(expr->astOperand1()->varId(), *result);return;}long long intValue;if (!programMemory->getIntValue(expr->astOperand1()->varId(), &intValue)) {*error = true;return;}if (expr->str() == "+=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue + *result);else if (expr->str() == "-=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue - *result);else if (expr->str() == "*=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue * *result);else if (expr->str() == "/=" && *result != 0)programMemory->setIntValue(expr->astOperand1()->varId(), intValue / *result);else if (expr->str() == "%=" && *result != 0)programMemory->setIntValue(expr->astOperand1()->varId(), intValue % *result);else if (expr->str() == "&=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue & *result);else if (expr->str() == "|=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue | *result);else if (expr->str() == "^=")programMemory->setIntValue(expr->astOperand1()->varId(), intValue ^ *result);}else if (Token::Match(expr, "++|--")) {if (!expr->astOperand1() || expr->astOperand1()->varId() == 0U)*error = true;else {long long intValue;if (!programMemory->getIntValue(expr->astOperand1()->varId(), &intValue))*error = true;else {if (intValue == 0 &&expr->str() == "--" &&expr->astOperand1()->variable() &&expr->astOperand1()->variable()->isUnsigned())*error = true; // overflow*result = intValue + (expr->str() == "++" ? 1 : -1);programMemory->setIntValue(expr->astOperand1()->varId(), *result);}}}else if (expr->isArithmeticalOp() && expr->astOperand1() && expr->astOperand2()) {MathLib::bigint result1(0), result2(0);execute(expr->astOperand1(), programMemory, &result1, error);execute(expr->astOperand2(), programMemory, &result2, error);if (expr->str() == "+")*result = result1 + result2;else if (expr->str() == "-")*result = result1 - result2;else if (expr->str() == "*") {if (result2 && (result1 > std::numeric_limits<MathLib::bigint>::max()/result2))*error = true;else*result = result1 * result2;} else if (result2 == 0)*error = true;else if (expr->str() == "/")*result = result1 / result2;else if (expr->str() == "%")*result = result1 % result2;else if (expr->str() == "<<") {if (result2 < 0 || result1 < 0 || result2 >= MathLib::bigint_bits) { // don't perform UB*error= true;} else {*result = result1 << result2;}} else if (expr->str() == ">>") {if (result2 < 0) { // don't perform UB*error=true;} else {*result = result1 >> result2;}}}else if (expr->str() == "&&") {bool error1 = false;execute(expr->astOperand1(), programMemory, result, &error1);if (!error1 && *result == 0)*result = 0;else {bool error2 = false;execute(expr->astOperand2(), programMemory, result, &error2);if (error1 && error2)*error = true;if (error2)*result = 1;else*result = !!*result;}}else if (expr->str() == "||") {execute(expr->astOperand1(), programMemory, result, error);if (*result == 0 && *error == false)execute(expr->astOperand2(), programMemory, result, error);}else if (expr->str() == "!") {execute(expr->astOperand1(), programMemory, result, error);*result = !(*result);}else if (expr->str() == "," && expr->astOperand1() && expr->astOperand2()) {execute(expr->astOperand1(), programMemory, result, error);execute(expr->astOperand2(), programMemory, result, error);}else if (expr->str() == "[" && expr->astOperand1() && expr->astOperand2()) {const Token *tokvalue = nullptr;if (!programMemory->getTokValue(expr->astOperand1()->varId(), &tokvalue)) {auto tokvalue_it = std::find_if(expr->astOperand1()->values().begin(),expr->astOperand1()->values().end(),std::mem_fn(&ValueFlow::Value::isTokValue));if (tokvalue_it == expr->astOperand1()->values().end()) {*error = true;return;}tokvalue = tokvalue_it->tokvalue;}if (!tokvalue || !tokvalue->isLiteral()) {*error = true;return;}const std::string strValue = tokvalue->strValue();MathLib::bigint index = 0;execute(expr->astOperand2(), programMemory, &index, error);if (index >= 0 && index < strValue.size())*result = strValue[index];else if (index == strValue.size())*result = 0;else*error = true;}else*error = true;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。