@@ -45,6 +45,7 @@ static constexpr char ATTR_CALL_ARGNR[] = "call-argnr";
45
45
static constexpr char ATTR_CALL_ARGEXPR[] = " call-argexpr" ;
46
46
static constexpr char ATTR_CALL_ARGVALUETYPE[] = " call-argvaluetype" ;
47
47
static constexpr char ATTR_CALL_ARGVALUE[] = " call-argvalue" ;
48
+ static constexpr char ATTR_CALL_UNKNOWN_FUNCTION_RETURN[] = " call-argvalue-ufr" ;
48
49
static constexpr char ATTR_WARNING[] = " warning" ;
49
50
static constexpr char ATTR_LOC_FILENAME[] = " file" ;
50
51
static constexpr char ATTR_LOC_LINENR[] = " line" ;
@@ -102,7 +103,8 @@ std::string CTU::FileInfo::FunctionCall::toXmlString() const
102
103
<< toBaseXmlString ()
103
104
<< " " << ATTR_CALL_ARGEXPR << " =\" " << ErrorLogger::toxml (callArgumentExpression) << " \" "
104
105
<< " " << 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 << " \" " ;
106
108
if (warning)
107
109
out << " " << ATTR_WARNING << " =\" true\" " ;
108
110
if (callValuePath.empty ())
@@ -201,7 +203,9 @@ bool CTU::FileInfo::FunctionCall::loadFromXml(const tinyxml2::XMLElement *xmlEle
201
203
bool error=false ;
202
204
callArgumentExpression = readAttrString (xmlElement, ATTR_CALL_ARGEXPR, &error);
203
205
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 );
205
209
const char *w = xmlElement->Attribute (ATTR_WARNING);
206
210
warning = w && std::strcmp (w, " true" ) == 0 ;
207
211
for (const tinyxml2::XMLElement *e2 = xmlElement->FirstChildElement (); !error && e2 ; e2 = e2 ->NextSiblingElement ()) {
@@ -342,7 +346,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
342
346
functionCall.location = FileInfo::Location (tokenizer,tok);
343
347
functionCall.callArgNr = argnr + 1 ;
344
348
functionCall.callArgumentExpression = argtok->expressionString ();
345
- functionCall.callArgValue = value. intvalue ;
349
+ functionCall.callArgValue = value;
346
350
functionCall.warning = !value.errorSeverity ();
347
351
for (const ErrorPathItem &i : value.errorPath ) {
348
352
const std::string& file = tokenizer.list .file (i.first );
@@ -364,7 +368,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
364
368
functionCall.callArgNr = argnr + 1 ;
365
369
functionCall.callArgumentExpression = argtok->expressionString ();
366
370
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 ;
368
372
functionCall.warning = false ;
369
373
fileInfo->functionCalls .push_back (std::move (functionCall));
370
374
}
@@ -377,7 +381,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
377
381
functionCall.location = FileInfo::Location (tokenizer, tok);
378
382
functionCall.callArgNr = argnr + 1 ;
379
383
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 );
381
385
functionCall.warning = false ;
382
386
fileInfo->functionCalls .push_back (std::move (functionCall));
383
387
}
@@ -411,7 +415,8 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
411
415
functionCall.callFunctionName = tok->astOperand1 ()->expressionString ();
412
416
functionCall.location = FileInfo::Location (tokenizer, tok);
413
417
functionCall.callArgNr = argnr + 1 ;
414
- functionCall.callArgValue = 0 ;
418
+ functionCall.callArgValue = v;
419
+ functionCall.callArgValue .value = 0 ;
415
420
functionCall.callArgumentExpression = argtok->expressionString ();
416
421
functionCall.warning = false ;
417
422
fileInfo->functionCalls .push_back (std::move (functionCall));
@@ -436,9 +441,9 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer)
436
441
return fileInfo;
437
442
}
438
443
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))
440
445
{
441
- std::list <std::pair<const Token *, MathLib::bigint >> ret;
446
+ std::vector <std::pair<const Token *, CTU::FileInfo::Value >> ret;
442
447
const Variable * const argvar = scope->function ->getArgumentVar (argnr);
443
448
if (!argvar->isArrayOrPointer () && !argvar->isReference ())
444
449
return ret;
@@ -459,7 +464,7 @@ static std::list<std::pair<const Token *, MathLib::bigint>> getUnsafeFunction(co
459
464
}
460
465
if (tok2->variable () != argvar)
461
466
continue ;
462
- MathLib::bigint value = 0 ;
467
+ CTU::FileInfo::Value value;
463
468
if (!isUnsafeUsage (settings, tok2, &value))
464
469
return ret; // TODO: Is this a read? then continue..
465
470
ret.emplace_back (tok2, value);
@@ -468,7 +473,7 @@ static std::list<std::pair<const Token *, MathLib::bigint>> getUnsafeFunction(co
468
473
return ret;
469
474
}
470
475
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))
472
477
{
473
478
std::list<CTU::FileInfo::UnsafeUsage> unsafeUsage;
474
479
@@ -482,9 +487,9 @@ std::list<CTU::FileInfo::UnsafeUsage> CTU::getUnsafeUsage(const Tokenizer &token
482
487
483
488
// "Unsafe" functions unconditionally reads data before it is written..
484
489
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)) {
486
491
const Token *tok = v.first ;
487
- const MathLib::bigint val = v.second ;
492
+ const MathLib::bigint val = v.second . value ;
488
493
unsafeUsage.emplace_back (CTU::getFunctionId (tokenizer, function), argnr+1 , tok->str (), CTU::FileInfo::Location (tokenizer,tok), val);
489
494
}
490
495
}
@@ -518,9 +523,11 @@ static bool findPath(const std::string &callId,
518
523
if (functionCall) {
519
524
if (!warning && functionCall->warning )
520
525
continue ;
526
+ if (!warning && functionCall->callArgValue .unknownFunctionReturn != ValueFlow::Value::UnknownFunctionReturn::no)
527
+ continue ;
521
528
switch (invalidValue) {
522
529
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 )
524
531
continue ;
525
532
break ;
526
533
case CTU::FileInfo::InvalidValueType::uninit:
@@ -530,7 +537,7 @@ static bool findPath(const std::string &callId,
530
537
case CTU::FileInfo::InvalidValueType::bufferOverflow:
531
538
if (functionCall->callValueType != ValueFlow::Value::ValueType::BUFFER_SIZE)
532
539
continue ;
533
- if (unsafeValue < 0 || (unsafeValue >= functionCall->callArgValue && functionCall->callArgValue >= 0 ))
540
+ if (unsafeValue < 0 || (unsafeValue >= functionCall->callArgValue . value && functionCall->callArgValue . value >= 0 ))
534
541
break ;
535
542
continue ;
536
543
}
@@ -557,14 +564,21 @@ std::list<ErrorMessage::FileLocation> CTU::FileInfo::getErrorPath(InvalidValueTy
557
564
const char info[],
558
565
const FunctionCall ** const functionCallPtr,
559
566
bool warning,
560
- int maxCtuDepth)
567
+ int maxCtuDepth,
568
+ ValueFlow::Value::UnknownFunctionReturn *unknownFunctionReturn)
561
569
{
562
- std::list<ErrorMessage::FileLocation> locationList;
563
-
564
570
const CTU::FileInfo::CallBase *path[10 ] = {nullptr };
565
571
566
572
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;
568
582
569
583
const std::string value1 = (invalidValue == InvalidValueType::null) ? " null" : " uninitialized" ;
570
584
0 commit comments