@@ -45,6 +45,7 @@ static constexpr char ATTR_CALL_ARGNR[] = "call-argnr";
4545static constexpr char ATTR_CALL_ARGEXPR[] = " call-argexpr" ;
4646static constexpr char ATTR_CALL_ARGVALUETYPE[] = " call-argvaluetype" ;
4747static constexpr char ATTR_CALL_ARGVALUE[] = " call-argvalue" ;
48+ static constexpr char ATTR_CALL_UNKNOWN_FUNCTION_RETURN[] = " call-argvalue-ufr" ;
4849static constexpr char ATTR_WARNING[] = " warning" ;
4950static constexpr char ATTR_LOC_FILENAME[] = " file" ;
5051static constexpr char ATTR_LOC_LINENR[] = " line" ;
@@ -102,7 +103,8 @@ std::string CTU::FileInfo::FunctionCall::toXmlString() const
102103 << toBaseXmlString ()
103104 << " " << ATTR_CALL_ARGEXPR << " =\" " << ErrorLogger::toxml (callArgumentExpression) << " \" "
104105 << " " << ATTR_CALL_ARGVALUETYPE << " =\" " << static_cast <int >(callValueType) << " \" "
105- << " " << ATTR_CALL_ARGVALUE << " =\" " << callArgValue << " \" " ;
106+ << " " << ATTR_CALL_ARGVALUE << " =\" " << callArgValue.value << " \" "
107+ << " " << ATTR_CALL_UNKNOWN_FUNCTION_RETURN << " =\" " << (int )callArgValue.unknownFunctionReturn << " \" " ;
106108 if (warning)
107109 out << " " << ATTR_WARNING << " =\" true\" " ;
108110 if (callValuePath.empty ())
@@ -201,7 +203,9 @@ bool CTU::FileInfo::FunctionCall::loadFromXml(const tinyxml2::XMLElement *xmlEle
201203 bool error=false ;
202204 callArgumentExpression = readAttrString (xmlElement, ATTR_CALL_ARGEXPR, &error);
203205 callValueType = (ValueFlow::Value::ValueType)readAttrInt (xmlElement, ATTR_CALL_ARGVALUETYPE, &error);
204- callArgValue = readAttrInt (xmlElement, ATTR_CALL_ARGVALUE, &error);
206+ callArgValue.value = readAttrInt (xmlElement, ATTR_CALL_ARGVALUE, &error);
207+ const auto ufr = readAttrInt (xmlElement, ATTR_CALL_UNKNOWN_FUNCTION_RETURN, &error);
208+ callArgValue.unknownFunctionReturn = (ValueFlow::Value::UnknownFunctionReturn)(ufr>=0 && ufr <=0xff ? ufr : 0xff );
205209 const char *w = xmlElement->Attribute (ATTR_WARNING);
206210 warning = w && std::strcmp (w, " true" ) == 0 ;
207211 for (const tinyxml2::XMLElement *e2 = xmlElement->FirstChildElement (); !error && e2 ; e2 = e2 ->NextSiblingElement ()) {
@@ -342,7 +346,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
342346 functionCall.location = FileInfo::Location (tokenizer,tok);
343347 functionCall.callArgNr = argnr + 1 ;
344348 functionCall.callArgumentExpression = argtok->expressionString ();
345- functionCall.callArgValue = value. intvalue ;
349+ functionCall.callArgValue = value;
346350 functionCall.warning = !value.errorSeverity ();
347351 for (const ErrorPathItem &i : value.errorPath ) {
348352 const std::string& file = tokenizer.list .file (i.first );
@@ -364,7 +368,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
364368 functionCall.callArgNr = argnr + 1 ;
365369 functionCall.callArgumentExpression = argtok->expressionString ();
366370 const auto typeSize = argtok->valueType ()->typeSize (tokenizer.getSettings ().platform );
367- functionCall.callArgValue = typeSize > 0 ? argtok->variable ()->dimension (0 ) * typeSize : -1 ;
371+ functionCall.callArgValue . value = typeSize > 0 ? argtok->variable ()->dimension (0 ) * typeSize : -1 ;
368372 functionCall.warning = false ;
369373 fileInfo->functionCalls .push_back (std::move (functionCall));
370374 }
@@ -377,7 +381,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
377381 functionCall.location = FileInfo::Location (tokenizer, tok);
378382 functionCall.callArgNr = argnr + 1 ;
379383 functionCall.callArgumentExpression = argtok->expressionString ();
380- functionCall.callArgValue = argtok->astOperand1 ()->valueType ()->typeSize (tokenizer.getSettings ().platform );
384+ functionCall.callArgValue . value = argtok->astOperand1 ()->valueType ()->typeSize (tokenizer.getSettings ().platform );
381385 functionCall.warning = false ;
382386 fileInfo->functionCalls .push_back (std::move (functionCall));
383387 }
@@ -411,7 +415,8 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
411415 functionCall.callFunctionName = tok->astOperand1 ()->expressionString ();
412416 functionCall.location = FileInfo::Location (tokenizer, tok);
413417 functionCall.callArgNr = argnr + 1 ;
414- functionCall.callArgValue = 0 ;
418+ functionCall.callArgValue = v;
419+ functionCall.callArgValue .value = 0 ;
415420 functionCall.callArgumentExpression = argtok->expressionString ();
416421 functionCall.warning = false ;
417422 fileInfo->functionCalls .push_back (std::move (functionCall));
@@ -436,9 +441,9 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
436441 return fileInfo;
437442}
438443
439- static std::list <std::pair<const Token *, MathLib::bigint >> getUnsafeFunction (const Settings &settings, const Scope *scope, int argnr, bool (*isUnsafeUsage)(const Settings &settings, const Token *argtok, MathLib::bigint *value))
444+ static std::vector <std::pair<const Token *, CTU::FileInfo::Value >> getUnsafeFunction (const Settings &settings, const Scope *scope, int argnr, bool (*isUnsafeUsage)(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *value))
440445{
441- std::list <std::pair<const Token *, MathLib::bigint >> ret;
446+ std::vector <std::pair<const Token *, CTU::FileInfo::Value >> ret;
442447 const Variable * const argvar = scope->function ->getArgumentVar (argnr);
443448 if (!argvar->isArrayOrPointer () && !argvar->isReference ())
444449 return ret;
@@ -459,7 +464,7 @@ static std::list<std::pair<const Token *, MathLib::bigint>> getUnsafeFunction(co
459464 }
460465 if (tok2->variable () != argvar)
461466 continue ;
462- MathLib::bigint value = 0 ;
467+ CTU::FileInfo::Value value;
463468 if (!isUnsafeUsage (settings, tok2, &value))
464469 return ret; // TODO: Is this a read? then continue..
465470 ret.emplace_back (tok2, value);
@@ -468,7 +473,7 @@ static std::list<std::pair<const Token *, MathLib::bigint>> getUnsafeFunction(co
468473 return ret;
469474}
470475
471- std::list<CTU::FileInfo::UnsafeUsage> CTU::getUnsafeUsage (const Tokenizer &tokenizer, const Settings &settings, bool (*isUnsafeUsage)(const Settings &settings, const Token *argtok, MathLib::bigint *value))
476+ std::list<CTU::FileInfo::UnsafeUsage> CTU::getUnsafeUsage (const Tokenizer &tokenizer, const Settings &settings, bool (*isUnsafeUsage)(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *value))
472477{
473478 std::list<CTU::FileInfo::UnsafeUsage> unsafeUsage;
474479
@@ -482,9 +487,9 @@ std::list<CTU::FileInfo::UnsafeUsage> CTU::getUnsafeUsage(const Tokenizer &token
482487
483488 // "Unsafe" functions unconditionally reads data before it is written..
484489 for (int argnr = 0 ; argnr < function->argCount (); ++argnr) {
485- for (const std::pair<const Token *, MathLib::bigint > &v : getUnsafeFunction (settings, &scope, argnr, isUnsafeUsage)) {
490+ for (const std::pair<const Token *, CTU::FileInfo::Value > &v : getUnsafeFunction (settings, &scope, argnr, isUnsafeUsage)) {
486491 const Token *tok = v.first ;
487- const MathLib::bigint val = v.second ;
492+ const MathLib::bigint val = v.second . value ;
488493 unsafeUsage.emplace_back (CTU::getFunctionId (tokenizer, function), argnr+1 , tok->str (), CTU::FileInfo::Location (tokenizer,tok), val);
489494 }
490495 }
@@ -518,9 +523,11 @@ static bool findPath(const std::string &callId,
518523 if (functionCall) {
519524 if (!warning && functionCall->warning )
520525 continue ;
526+ if (!warning && functionCall->callArgValue .unknownFunctionReturn != ValueFlow::Value::UnknownFunctionReturn::no)
527+ continue ;
521528 switch (invalidValue) {
522529 case CTU::FileInfo::InvalidValueType::null:
523- if (functionCall->callValueType != ValueFlow::Value::ValueType::INT || functionCall->callArgValue != 0 )
530+ if (functionCall->callValueType != ValueFlow::Value::ValueType::INT || functionCall->callArgValue . value != 0 )
524531 continue ;
525532 break ;
526533 case CTU::FileInfo::InvalidValueType::uninit:
@@ -530,7 +537,7 @@ static bool findPath(const std::string &callId,
530537 case CTU::FileInfo::InvalidValueType::bufferOverflow:
531538 if (functionCall->callValueType != ValueFlow::Value::ValueType::BUFFER_SIZE)
532539 continue ;
533- if (unsafeValue < 0 || (unsafeValue >= functionCall->callArgValue && functionCall->callArgValue >= 0 ))
540+ if (unsafeValue < 0 || (unsafeValue >= functionCall->callArgValue . value && functionCall->callArgValue . value >= 0 ))
534541 break ;
535542 continue ;
536543 }
@@ -557,14 +564,21 @@ std::list<ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(InvalidValueTy
557564 const char info[],
558565 const FunctionCall ** const functionCallPtr,
559566 bool warning,
560- int maxCtuDepth)
567+ int maxCtuDepth,
568+ ValueFlow::Value::UnknownFunctionReturn *unknownFunctionReturn)
561569{
562- std::list<ErrorMessage::FileLocation> locationList;
563-
564570 const CTU::FileInfo::CallBase *path[10 ] = {nullptr };
565571
566572 if (!findPath (unsafeUsage.myId , unsafeUsage.myArgNr , unsafeUsage.value , invalidValue, callsMap, path, 0 , warning, maxCtuDepth))
567- return locationList;
573+ return {};
574+
575+ if (unknownFunctionReturn && path[0 ]) {
576+ const auto * functionCall = dynamic_cast <const CTU::FileInfo::FunctionCall *>(path[0 ]);
577+ if (functionCall)
578+ *unknownFunctionReturn = functionCall->callArgValue .unknownFunctionReturn ;
579+ }
580+
581+ std::list<ErrorMessage::FileLocation> locationList;
568582
569583 const std::string value1 = (invalidValue == InvalidValueType::null) ? " null" : " uninitialized" ;
570584
0 commit comments