MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / stringNotZeroTerminated

Method stringNotZeroTerminated

lib/checkbufferoverrun.cpp:758–809  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

756//---------------------------------------------------------------------------
757
758void CheckBufferOverrunImpl::stringNotZeroTerminated()
759{
760 // this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3
761 if (!mSettings.severity.isEnabled(Severity::warning) || !mSettings.certainty.isEnabled(Certainty::inconclusive))
762 return;
763
764 logChecker("CheckBufferOverrun::stringNotZeroTerminated"); // warning,inconclusive
765
766 const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
767 for (const Scope * const scope : symbolDatabase->functionScopes) {
768 for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) {
769 if (!Token::simpleMatch(tok, "strncpy ("))
770 continue;
771 const std::vector<const Token *> args = getArguments(tok);
772 if (args.size() != 3)
773 continue;
774 const Token *sizeToken = args[2];
775 if (!sizeToken->hasKnownIntValue())
776 continue;
777 const ValueFlow::Value &bufferSize = getBufferSize(args[0]);
778 if (bufferSize.intvalue < 0 || sizeToken->getKnownIntValue() < bufferSize.intvalue)
779 continue;
780 if (Token::simpleMatch(args[1], "(") && Token::simpleMatch(args[1]->astOperand1(), ". c_str") && args[1]->astOperand1()->astOperand1()) {
781 const std::list<ValueFlow::Value>& contValues = args[1]->astOperand1()->astOperand1()->values();
782 auto it = std::find_if(contValues.cbegin(), contValues.cend(), [](const ValueFlow::Value& value) {
783 return value.isContainerSizeValue() && !value.isImpossible();
784 });
785 if (it != contValues.end() && it->intvalue < sizeToken->getKnownIntValue())
786 continue;
787 } else {
788 const Token* srcValue = args[1]->getValueTokenMaxStrLength();
789 if (srcValue && Token::getStrLength(srcValue) < sizeToken->getKnownIntValue())
790 continue;
791 }
792 // Is the buffer zero terminated after the call?
793 bool isZeroTerminated = false;
794 for (const Token *tok2 = tok->linkAt(1); tok2 != scope->bodyEnd; tok2 = tok2->next()) {
795 if (!Token::simpleMatch(tok2, "] ="))
796 continue;
797 const Token *rhs = tok2->next()->astOperand2();
798 if (!rhs || !rhs->hasKnownIntValue() || rhs->getKnownIntValue() != 0)
799 continue;
800 if (isSameExpression(false, args[0], tok2->link()->astOperand1(), mSettings, false, false))
801 isZeroTerminated = true;
802 }
803 if (isZeroTerminated)
804 continue;
805 // TODO: Locate unsafe string usage..
806 terminateStrncpyError(tok, getRealBufferTok(args[0])->expressionString());
807 }
808 }
809}
810
811void CheckBufferOverrunImpl::terminateStrncpyError(const Token *tok, const std::string &varname)
812{

Callers 1

runChecksMethod · 0.80

Calls 15

isSameExpressionFunction · 0.85
getRealBufferTokFunction · 0.85
nextMethod · 0.80
getKnownIntValueMethod · 0.80
astOperand1Method · 0.80
isImpossibleMethod · 0.80
linkAtMethod · 0.80
astOperand2Method · 0.80
simpleMatchFunction · 0.70
getArgumentsFunction · 0.70
isEnabledMethod · 0.45

Tested by

no test coverage detected