Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ $(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/checkers.h lib
$(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/timer.cpp

$(libcppdir)/token.o: lib/token.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/valueflow.h lib/vfvalue.h
$(libcppdir)/token.o: lib/token.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/tokenrange.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/token.cpp

$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/astutils.h lib/checkers.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
Expand All @@ -690,7 +690,7 @@ $(libcppdir)/vf_analyzers.o: lib/vf_analyzers.cpp lib/analyzer.h lib/astutils.h
$(libcppdir)/vf_common.o: lib/vf_common.cpp lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_common.cpp

$(libcppdir)/vf_settokenvalue.o: lib/vf_settokenvalue.cpp lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h
$(libcppdir)/vf_settokenvalue.o: lib/vf_settokenvalue.cpp lib/astutils.h lib/calculate.h lib/checkers.h lib/config.h lib/errortypes.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_common.h lib/vf_settokenvalue.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_settokenvalue.cpp

$(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/smallvector.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h
Expand Down Expand Up @@ -957,7 +957,7 @@ test/testutils.o: test/testutils.cpp lib/check.h lib/checkers.h lib/color.h lib/
test/testvaarg.o: test/testvaarg.cpp lib/check.h lib/checkers.h lib/checkimpl.h lib/checkvaarg.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvaarg.cpp

test/testvalueflow.o: test/testvalueflow.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
test/testvalueflow.o: test/testvalueflow.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueptr.h lib/vf_common.h lib/vfvalue.h test/fixture.h test/helpers.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvalueflow.cpp

test/testvarid.o: test/testvarid.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
Expand Down
59 changes: 59 additions & 0 deletions lib/checkbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,69 @@ void CheckBufferOverrunImpl::arrayIndex()
arrayIndexError(tok, dimensions, indexValues);
}

const auto isNonnegativeInductionVariable = [&](const Token* indexToken) {
const Variable* const variable = indexToken->variable();
if (!variable || !indexToken->varId())
return false;

for (const Scope* loop = indexToken->scope(); loop; loop = loop->nestedIn) {
if (loop->type != ScopeType::eFor || !loop->classDef || !loop->bodyStart || !loop->bodyEnd)
continue;
const Token* const forExpressions = loop->classDef->next();
if (!forExpressions || !forExpressions->astOperand2())
continue;
const Token* const clauses = forExpressions->astOperand2();
const Token* const init = clauses->astOperand1();
const Token* const remainingClauses = clauses->astOperand2();
if (!init || !remainingClauses || !remainingClauses->astOperand1() || !remainingClauses->astOperand2())
continue;
const Token* const step = remainingClauses->astOperand2();
if (!Token::simpleMatch(init, "=") || !init->astOperand1() ||
init->astOperand1()->varId() != indexToken->varId() || !Token::simpleMatch(step, "++"))
continue;
const Token* stepVariable = step->astOperand1();
if (!stepVariable)
stepVariable = step->astOperand2();
if (!stepVariable || stepVariable->varId() != indexToken->varId())
continue;

const Token* const initialValue = init->astOperand2();
const ValueType* const initialType = initialValue ? initialValue->valueType() : nullptr;
const ValueType* const indexType = indexToken->valueType();
if (!initialValue || !initialType || !indexType || !initialType->isIntegral() || !indexType->isIntegral() ||
initialType->pointer || indexType->pointer || initialType->sign != indexType->sign ||
initialType->getSizeOf(mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer) >
indexType->getSizeOf(mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer))
continue;
const bool hasNonnegativeLowerBound = std::any_of(initialValue->values().cbegin(),
initialValue->values().cend(),
[](const ValueFlow::Value& value) {
return value.isIntValue() && !value.isImpossible() && !value.isInconclusive() && value.intvalue >= 0 &&
(value.bound == ValueFlow::Value::Bound::Lower ||
(value.bound == ValueFlow::Value::Bound::Point && value.isKnown()));
});
if (!hasNonnegativeLowerBound)
continue;
if (findVariableChanged(loop->bodyStart->next(),
loop->bodyEnd,
/*indirect*/ 1,
variable->declarationId(),
variable->isGlobal(),
mSettings))
continue;
return true;
}
return false;
};

// Negative index
bool neg = false;
std::vector<ValueFlow::Value> negativeIndexes;
for (const Token * indexToken : indexTokens) {
if (isNonnegativeInductionVariable(indexToken)) {
negativeIndexes.emplace_back(ValueFlow::Value::unknown());
continue;
}
const ValueFlow::Value *negativeValue = indexToken->getValueLE(-1, mSettings);
if (negativeValue) {
negativeIndexes.emplace_back(*negativeValue);
Expand Down
43 changes: 40 additions & 3 deletions lib/checktype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,49 @@ void CheckTypeImpl::checkTooBigBitwiseShift()
else
continue;

// Get biggest rhs value. preferably a value which doesn't have 'condition'.
const ValueFlow::Value * value = tok->astOperand2()->getValueGE(lhsbits, mSettings);
// Get the biggest feasible rhs value, preferring a value without a condition.
const Token* const shiftCount = tok->astOperand2();
const auto isUnreachableTernaryValue = [&](const ValueFlow::Value& candidate) {
const Token* child = shiftCount;
for (const Token* parent = child->astParent(); parent; child = parent, parent = parent->astParent()) {
if (parent->str() != ":" || !Token::simpleMatch(parent->astParent(), "?"))
continue;
const bool inTrueBranch = child == parent->astOperand1();
const bool inFalseBranch = child == parent->astOperand2();
if (!inTrueBranch && !inFalseBranch)
continue;
const Token* condition = parent->astParent()->astOperand1();
bool canEnterBranch = false;
bool canEnterOtherBranch = false;
for (const ValueFlow::Value& value : condition->values()) {
if (!value.isIntValue() || value.isImpossible() || value.bound != ValueFlow::Value::Bound::Point ||
(value.path != 0 && (candidate.path == 0 || value.path != candidate.path)))
continue;
if ((value.intvalue != 0) == inTrueBranch)
canEnterBranch = true;
else
canEnterOtherBranch = true;
}
return canEnterOtherBranch && !canEnterBranch;
}
return false;
};
const auto getShiftCountValueGE = [&](MathLib::bigint threshold) -> const ValueFlow::Value* {
return ValueFlow::findValue(shiftCount->values(), mSettings, [&](const ValueFlow::Value& candidate) {
if (candidate.isImpossible() || !candidate.isIntValue() || candidate.intvalue < threshold ||
isUnreachableTernaryValue(candidate))
return false;
return std::none_of(shiftCount->values().cbegin(), shiftCount->values().cend(), [&](const ValueFlow::Value& bound) {
return bound.isImpossible() && bound.isIntValue() && bound.bound == ValueFlow::Value::Bound::Lower &&
bound.intvalue <= threshold && (bound.path == 0 || bound.path == candidate.path);
});
});
};
const ValueFlow::Value * value = getShiftCountValueGE(lhsbits);
if (value && mSettings.isEnabled(value, false))
tooBigBitwiseShiftError(tok, lhsbits, *value);
else if (lhstype->sign == ValueType::Sign::SIGNED) {
value = tok->astOperand2()->getValueGE(lhsbits-1, mSettings);
value = getShiftCountValueGE(lhsbits - 1);
if (value && mSettings.isEnabled(value, false))
tooBigSignedBitwiseShiftError(tok, lhsbits, *value);
}
Expand Down
Loading
Loading