Skip to content

Commit 08f0993

Browse files
author
Jean-François DEVERGE
committed
Fix #15000: Propagate integral cast ranges with path-safe value flow
1 parent b2d8361 commit 08f0993

25 files changed

Lines changed: 3205 additions & 359 deletions

‎.github/workflows/CI-cygwin.yml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ jobs:
4444
- name: Set up Cygwin
4545
uses: cygwin/cygwin-install-action@v6
4646
with:
47-
site: https://mirrors.cicku.me/cygwin/
4847
platform: ${{ matrix.platform }}
4948
packages: ${{ matrix.packages }}
5049

‎Makefile‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ $(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/checkers.h lib
675675
$(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h
676676
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/timer.cpp
677677

678-
$(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
678+
$(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
679679
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/token.cpp
680680

681681
$(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
@@ -690,7 +690,7 @@ $(libcppdir)/vf_analyzers.o: lib/vf_analyzers.cpp lib/analyzer.h lib/astutils.h
690690
$(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
691691
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_common.cpp
692692

693-
$(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
693+
$(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
694694
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_settokenvalue.cpp
695695

696696
$(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
@@ -957,7 +957,7 @@ test/testutils.o: test/testutils.cpp lib/check.h lib/checkers.h lib/color.h lib/
957957
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
958958
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvaarg.cpp
959959

960-
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
960+
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
961961
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvalueflow.cpp
962962

963963
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

‎lib/checkbufferoverrun.cpp‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,77 @@ void CheckBufferOverrunImpl::arrayIndex()
355355
arrayIndexError(tok, dimensions, indexValues);
356356
}
357357

358+
const auto isNonnegativeInductionVariable = [&](const Token* indexToken) {
359+
const Variable* const variable = indexToken->variable();
360+
if (!variable || !indexToken->varId())
361+
return false;
362+
363+
for (const Scope* loop = indexToken->scope(); loop; loop = loop->nestedIn) {
364+
if (loop->type != ScopeType::eFor || !loop->classDef || !loop->bodyStart || !loop->bodyEnd)
365+
continue;
366+
const Token* const forExpressions = loop->classDef->next();
367+
if (!forExpressions || !forExpressions->astOperand2())
368+
continue;
369+
const Token* const clauses = forExpressions->astOperand2();
370+
const Token* const init = clauses->astOperand1();
371+
const Token* const remainingClauses = clauses->astOperand2();
372+
if (!init || !remainingClauses || !remainingClauses->astOperand1() || !remainingClauses->astOperand2())
373+
continue;
374+
const Token* const step = remainingClauses->astOperand2();
375+
if (!Token::simpleMatch(init, "=") || !init->astOperand1() ||
376+
init->astOperand1()->varId() != indexToken->varId() || !Token::simpleMatch(step, "++"))
377+
continue;
378+
const Token* stepVariable = step->astOperand1();
379+
if (!stepVariable)
380+
stepVariable = step->astOperand2();
381+
if (!stepVariable || stepVariable->varId() != indexToken->varId())
382+
continue;
383+
384+
const Token* const initialValue = init->astOperand2();
385+
const ValueType* const initialType = initialValue ? initialValue->valueType() : nullptr;
386+
const ValueType* const indexType = indexToken->valueType();
387+
if (!initialValue || !initialType || !indexType || !initialType->isIntegral() || !indexType->isIntegral() ||
388+
initialType->pointer || indexType->pointer || initialType->sign != indexType->sign ||
389+
initialType->getSizeOf(mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer) >
390+
indexType->getSizeOf(mSettings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer))
391+
continue;
392+
const bool hasNonnegativeLowerBound = std::any_of(initialValue->values().cbegin(),
393+
initialValue->values().cend(),
394+
[](const ValueFlow::Value& value) {
395+
return value.isIntValue() && !value.isImpossible() && !value.isInconclusive() && value.intvalue >= 0 &&
396+
(value.bound == ValueFlow::Value::Bound::Lower ||
397+
(value.bound == ValueFlow::Value::Bound::Point && value.isKnown()));
398+
});
399+
if (!hasNonnegativeLowerBound)
400+
continue;
401+
const Token* const condition = remainingClauses->astOperand1();
402+
if (findVariableChanged(previousBeforeAstLeftmostLeaf(condition)->next(),
403+
nextAfterAstRightmostLeaf(condition),
404+
/*indirect*/ 0,
405+
variable->declarationId(),
406+
variable->isGlobal(),
407+
mSettings))
408+
continue;
409+
if (findVariableChanged(loop->bodyStart->next(),
410+
loop->bodyEnd,
411+
/*indirect*/ 1,
412+
variable->declarationId(),
413+
variable->isGlobal(),
414+
mSettings))
415+
continue;
416+
return true;
417+
}
418+
return false;
419+
};
420+
358421
// Negative index
359422
bool neg = false;
360423
std::vector<ValueFlow::Value> negativeIndexes;
361424
for (const Token * indexToken : indexTokens) {
425+
if (isNonnegativeInductionVariable(indexToken)) {
426+
negativeIndexes.emplace_back(ValueFlow::Value::unknown());
427+
continue;
428+
}
362429
const ValueFlow::Value *negativeValue = indexToken->getValueLE(-1, mSettings);
363430
if (negativeValue) {
364431
negativeIndexes.emplace_back(*negativeValue);

0 commit comments

Comments
 (0)