SlideShare une entreprise Scribd logo
1  sur  10
Télécharger pour lire hors ligne
Checking Clang 11 with PVS-Studio
Author: Andrey Karpov
Date: 27.10.2020
Tags: Cpp, Compiler
Every now and then, we have to write articles about how we've checked another fresh version of some
compiler. That's not really much fun. However, as practice shows, if we stop doing that for a while, folks
start doubting whether PVS-Studio is worth its title of a good catcher of bugs and vulnerabilities. What if
the new compiler can do that too? Sure, compilers evolve, but so does PVS-Studio – and it proves, again
and again, its ability to catch bugs even in high-quality projects such as compilers.
Time for rechecking Clang
To tell you the truth, I wrote this article based on the earlier post "Checking the GCC 10 Compiler with
PVS-Studio". So if some paragraphs seem familiar, it's because you've already read them before :).
It's no secret that compilers employ their own built-in static code analyzers, and those are developing as
well. That's why we write articles every now and then to show that our static analyzer, PVS-Studio, can
find bugs even inside compilers and that we are worth our salt :).
In fact, you can't compare classic static analyzers with compilers. Static analyzers not only detect bugs in
source code but also involve a highly developed infrastructure. For one thing, it includes integration with
such systems as SonarQube, PlatformIO, Azure DevOps, Travis CI, CircleCI, GitLab CI/CD, Jenkins, and
Visual Studio. It includes mechanisms for mass suppression of warnings, which allows you to start using
PVS-Studio right off even in a large project. It includes sending notifications by email. And so on and so
forth. But the first question developers will still ask is, "Can your PVS-Studio find anything that compilers
can't?" And that means we are doomed to write articles about how we check the compilers themselves
over and over again.
Let's get back to Clang. There's no need to dwell on the subject and tell you what the project is about.
Actually, we checked not only the code of Clang 11 itself but also the code of the LLVM 11 library it's
based on. From this article's viewpoint, it doesn't matter if a defect was found in the compiler's or the
library's code.
I found the code of Clang/LLVM much clearer than that of GCC. At least it's not teeming with all those
awful macros and it extensively employs C++'s modern features.
Even so, the project is still big enough to make examining the analysis report tedious without prior
customization. What mostly gets in the way is "semi-false" positives. By "semi-false" positives I mean
cases where the analyzer is technically correct to point out certain issues but those warnings are of no
practical use. For example, a lot of such warnings refer to unit tests and generated code.
Here's an example for unit tests:
Spaces.SpacesInParentheses = false; // <=
Spaces.SpacesInCStyleCastParentheses = true; // <=
verifyFormat("Type *A = ( Type * )P;", Spaces);
verifyFormat("Type *A = ( vector<Type *, int *> )P;", Spaces);
verifyFormat("x = ( int32 )y;", Spaces);
verifyFormat("int a = ( int )(2.0f);", Spaces);
verifyFormat("#define AA(X) sizeof((( X * )NULL)->a)", Spaces);
verifyFormat("my_int a = ( my_int )sizeof(int);", Spaces);
verifyFormat("#define x (( int )-1)", Spaces);
// Run the first set of tests again with:
Spaces.SpacesInParentheses = false; // <=
Spaces.SpaceInEmptyParentheses = true;
Spaces.SpacesInCStyleCastParentheses = true; // <=
verifyFormat("call(x, y, z);", Spaces);
verifyFormat("call( );", Spaces);
The analyzer warns us that the variables are assigned the same values they already have:
• V1048 The 'Spaces.SpacesInParentheses' variable was assigned the same value. FormatTest.cpp
11554
• V1048 The 'Spaces.SpacesInCStyleCastParentheses' variable was assigned the same value.
FormatTest.cpp 11556
Technically, this warning is to the point and the snippet needs simplifying or fixing. But it's also clear that
this code is fine as it is and there's no point fixing anything in it.
Here's another example: the analyzer outputs a ton of warnings on the autogenerated file Options.inc.
Look at the "wall" of code it contains:
This bulk of code triggers a flood of warnings:
• V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr
== nullptr Options.inc 26
• V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr
== nullptr Options.inc 27
• V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr
== nullptr Options.inc 28
• and so on – one warning per line...
Yet all that is not a big deal. It can be solved by excluding irrelevant files from analysis, marking certain
macros and functions, suppressing certain diagnostic types, and so on. Yes, it can, but it's not a very
interesting job to do when you write an article. That's why I did the same thing as in the article about
checking the GCC compiler: I kept reading the report until I collected 11 interesting examples to include
in the article. Why 11? I just thought that since it was the 11-th version of Clang, I needed 11 examples
:).
11 suspicious code snippets
Snippet 1, modulo operation on 1
This is a cool one! I like bugs like that!
void Act() override {
....
// If the value type is a vector, and we allow vector select, then in 50%
// of the cases generate a vector select.
if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 1)) {
unsigned NumElem =
cast<FixedVectorType>(Val0->getType())->getNumElements();
CondTy = FixedVectorType::get(CondTy, NumElem);
}
....
}
PVS-Studio diagnostic message: V1063 The modulo by 1 operation is meaningless. The result will always
be zero. llvm-stress.cpp 631
The programmer is using a modulo operation to get a random value of either 0 or 1. But the value 1
seems to confuse developers and make them write the classic anti-pattern in which the modulo
operation is performed on 1 instead of 2. The X % 1 operation is meaningless as it always evaluates to 0.
This is the fixed version:
if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 2)) {
The recently added V1063 diagnostic is awfully simple, but, as you can see, it works perfectly.
We know that compiler developers keep an eye on our work and borrow our ideas. That's totally fine.
It's nice to know that PVS-Studio is the driving force behind progress. Let's see how much it will take for
a similar diagnostic to appear in Clang and GCC :).
Snippet 2, a typo in a condition
class ReturnValueSlot {
....
bool isNull() const { return !Addr.isValid(); }
....
};
static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
const FunctionDecl *F2, unsigned NumParams) {
....
unsigned I1 = 0, I2 = 0;
for (unsigned I = 0; I != NumParams; ++I) {
QualType T1 = NextParam(F1, I1, I == 0);
QualType T2 = NextParam(F2, I2, I == 0);
if (!T1.isNull() && !T1.isNull() && !Context.hasSameUnqualifiedType(T1, T2))
return false;
}
return true;
}
PVS-Studio diagnostic message: V501 There are identical sub-expressions to the left and to the right of
the '&&' operator: !T1.isNull() && !T1.isNull() SemaOverload.cpp 9493
The !T1.isNull() check is performed twice. This is obviously a typo; the second part of the condition must
check the T2 variable.
Snippet 3, potential array-index-out-of-bounds
std::vector<Decl *> DeclsLoaded;
SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
....
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
if (Index > DeclsLoaded.size()) {
Error("declaration ID out-of-range for AST file");
return SourceLocation();
}
if (Decl *D = DeclsLoaded[Index])
return D->getLocation();
....
}
PVS-Studio diagnostic message: V557 Array overrun is possible. The 'Index' index is pointing beyond
array bound. ASTReader.cpp 7318
Suppose the array stores one element and the value of the Index variable is also 1. Then the (1 > 1)
condition is false, and, therefore, the array will be indexed beyond its bounds. Here's the correct check:
if (Index >= DeclsLoaded.size()) {
Snippet 4, argument evaluation order
void IHexELFBuilder::addDataSections() {
....
uint32_t SecNo = 1;
....
Section = &Obj->addSection<OwnedDataSection>(
".sec" + std::to_string(SecNo++), RecAddr,
ELF::SHF_ALLOC | ELF::SHF_WRITE, SecNo);
....
}
PVS-Studio diagnostic message: V567 Unspecified behavior. The order of argument evaluation is not
defined for 'addSection' function. Consider inspecting the 'SecNo' variable. Object.cpp 1223
Note that the SecNo argument is used twice, getting incremented in the meanwhile. The problem is, you
can't tell in what exact order the arguments will be evaluated. The result will, therefore, vary depending
on the compiler version or compilation parameters.
Here's a synthetic example to illustrate this point:
#include <cstdio>
int main()
{
int i = 1;
printf("%d, %dn", i, i++);
return 0;
}
Depending on the compiler, this code may output either "1, 1" or "2, 1". I ran it on Compiler Explorer
and got the following outputs:
• when compiled with Clang 11.0.0, the program outputs 1, 1.
• when compiled with GCC 10.2, the program outputs 2, 1.
Interestingly, this simple case causes Clang to issue a warning:
<source>:6:26: warning:
unsequenced modification and access to 'i' [-Wunsequenced]
printf("%d, %dn", i, i++);
For some reason, though, this warning wasn't issued on the real code. Either it's disabled as a not very
practical one or that case is too complicated for the compiler to cope with.
Snippet 5, a strange duplicate check
template <class ELFT>
void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
const Elf_Shdr *Sec) {
....
Expected<StringRef> NameOrErr =
this->dumper()->getSymbolVersionByIndex(Ndx, IsDefault);
if (!NameOrErr) {
if (!NameOrErr) {
unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
this->reportUniqueWarning(createError(
"unable to get a version for entry " + Twine(I) +
" of SHT_GNU_versym section with index " + Twine(SecNdx) + ": " +
toString(NameOrErr.takeError())));
}
Versions.emplace_back("<corrupt>");
continue;
}
....
}
PVS-Studio diagnostic message: V571 Recurring check. The 'if (!NameOrErr)' condition was already
verified in line 4666. ELFDumper.cpp 4667
The second check is a clone of the first and is, therefore, redundant. Maybe it could be safely removed.
But what's more likely is that it contains a typo and was meant to check some other variable.
Snippet 6, potential null pointer dereference
void RewriteObjCFragileABI::RewriteObjCClassMetaData(
ObjCImplementationDecl *IDecl, std::string &Result)
{
ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
if (CDecl->isImplicitInterfaceDecl()) {
RewriteObjCInternalStruct(CDecl, Result);
}
unsigned NumIvars = !IDecl->ivar_empty()
? IDecl->ivar_size()
: (CDecl ? CDecl->ivar_size() : 0);
....
}
PVS-Studio diagnostic message: V595 The 'CDecl' pointer was utilized before it was verified against
nullptr. Check lines: 5275, 5284. RewriteObjC.cpp 5275
When performing the first check, the developer never hesitates to dereference the CDecl pointer:
if (CDecl->isImplicitInterfaceDecl())
But if you look at the code a few lines further, it becomes clear that the pointer can be null:
(CDecl ? CDecl->ivar_size() : 0)
The first check was probably meant to look like this:
if (CDecl && CDecl->isImplicitInterfaceDecl())
Snippet 7, potential null pointer dereference
bool
Sema::InstantiateClass(....)
{
....
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
CXXRecordDecl *ThisContext =
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND && ND->isCXXInstanceMember());
....
}
PVS-Studio diagnostic message: V595 The 'ND' pointer was utilized before it was verified against nullptr.
Check lines: 2803, 2805. SemaTemplateInstantiate.cpp 2803
This error is similar to the previous one. It's dangerous to dereference a pointer without a prior check
when its value is acquired using a dynamic type cast. More than that, subsequent code confirms that
such a check is needed.
Snippet 8, a function keeping running despite an error state
bool VerifyObject(llvm::yaml::Node &N,
std::map<std::string, std::string> Expected) {
....
auto *V = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getValue());
if (!V) {
ADD_FAILURE() << KS << " is not a string";
Match = false;
}
std::string VS = V->getValue(Tmp).str();
....
}
PVS-Studio diagnostic message: V1004 The 'V' pointer was used unsafely after it was verified against
nullptr. Check lines: 61, 65. TraceTests.cpp 65
The V pointer may be a null pointer. This is obviously an error state, which is even reported with an
error message. But the function will just keep running as if nothing happened and will end up
dereferencing that very null pointer. The programmer probably wanted the function to stop at this
point, in which case it should be fixed as follows:
auto *V = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getValue());
if (!V) {
ADD_FAILURE() << KS << " is not a string";
Match = false;
return false;
}
std::string VS = V->getValue(Tmp).str();
Snippet 9, a typo
const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input,
const InputInfo &Output) {
if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
if (StringRef(A->getValue()) == "single")
return Args.MakeArgString(Output.getFilename());
Arg *FinalOutput = Args.getLastArg(options::OPT_o);
if (FinalOutput && Args.hasArg(options::OPT_c)) {
SmallString<128> T(FinalOutput->getValue());
llvm::sys::path::replace_extension(T, "dwo");
return Args.MakeArgString(T);
} else {
// Use the compilation dir.
SmallString<128> T(
Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
llvm::sys::path::replace_extension(F, "dwo");
T += F;
return Args.MakeArgString(F); // <=
}
}
PVS-Studio diagnostic message: V1001 The 'T' variable is assigned but is not used by the end of the
function. CommonArgs.cpp 873
Look at the last lines of the function. The local variable T changes but isn't used in any way. This must be
a typo and the function should probably end as follows:
T += F;
return Args.MakeArgString(T);
Snippet 10, zero as the divisor
typedef int32_t si_int;
typedef uint32_t su_int;
typedef union {
du_int all;
struct {
#if _YUGA_LITTLE_ENDIAN
su_int low;
su_int high;
#else
su_int high;
su_int low;
#endif // _YUGA_LITTLE_ENDIAN
} s;
} udwords;
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
....
if (d.s.low == 0) {
if (d.s.high == 0) {
// K X
// ---
// 0 0
if (rem)
*rem = n.s.high % d.s.low;
return n.s.high / d.s.low;
}
....
}
PVS-Studio diagnostic messages:
• V609 Mod by zero. Denominator 'd.s.low' == 0. udivmoddi4.c 61
• V609 Divide by zero. Denominator 'd.s.low' == 0. udivmoddi4.c 62
I don't know if this is a bug or some tricky contraption, but the code does look strange. It has two regular
integer variables, one of which is divided by the other. But the interesting part is that the division
operation takes place only if both variables are zeroes. What task is it supposed to accomplish?
Snippet 11, copy-paste
bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(....)
{
....
StringRef FName = II->getName();
....
if (FName == "postEvent" &&
FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
return true;
}
if (FName == "postEvent" &&
FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
return true;
}
....
}
PVS-Studio diagnostic message: V581 The conditional expressions of the 'if' statements situated
alongside each other are identical. Check lines: 3108, 3113. MallocChecker.cpp 3113
A code fragment was cloned but never modified afterwards. This clone should either be removed or
modified to perform some useful check.
Conclusion
{{GET_TRIAL_INSERT}}
Remember that you can use this free-license option to check open-source projects. We provide other
ways to use PVS-Studio for free as well, some of them even allowing analysis of proprietary code. See
the full list of options here: "Ways to Get a Free PVS-Studio License". Thank you for reading!
Further reading on checking compilers with PVS-Studio
1. Check of LLVM (Clang) (August 2011), second check (August 2012), third check (October 2016),
fourth check (April 2019)
2. Check of GCC (August 2016), second check (April 2020)
3. Check of Huawei Ark Compiler (December 2019)
4. Check of .NET Compiler Platform ("Roslyn") (December 2015), second check (April 2019)
5. Check of Roslyn Analyzers (August 2019)
6. Check of PascalABC.NET (March 2017)

Contenu connexe

Tendances

Tendances (20)

The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
Checking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerChecking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzer
 
Dusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectDusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind project
 
Source code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checkedSource code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checked
 
Checking VirtualDub
Checking VirtualDubChecking VirtualDub
Checking VirtualDub
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
CppCat Static Analyzer Review
CppCat Static Analyzer ReviewCppCat Static Analyzer Review
CppCat Static Analyzer Review
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 libraries
 
Checking the Qt 5 Framework
Checking the Qt 5 FrameworkChecking the Qt 5 Framework
Checking the Qt 5 Framework
 
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft EdgeChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More Time
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
 
Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
 
PVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 projectPVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 project
 
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorWaiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
 
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
 
Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016
 

Similaire à Checking Clang 11 with PVS-Studio

Similaire à Checking Clang 11 with PVS-Studio (20)

PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
Finding bugs in the code of LLVM project with the help of PVS-Studio
Finding bugs in the code of LLVM project with the help of PVS-StudioFinding bugs in the code of LLVM project with the help of PVS-Studio
Finding bugs in the code of LLVM project with the help of PVS-Studio
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
 
Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzer
 
Checking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-StudioChecking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-Studio
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
 
Looking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelopLooking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelop
 
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodeA Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
 
PVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernel
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
Heading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckHeading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th Check
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
PVS-Studio vs Chromium - Continuation
PVS-Studio vs Chromium - ContinuationPVS-Studio vs Chromium - Continuation
PVS-Studio vs Chromium - Continuation
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd Check
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 

Plus de Andrey Karpov

Plus de Andrey Karpov (20)

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
 

Dernier

%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 

Dernier (20)

MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 

Checking Clang 11 with PVS-Studio

  • 1. Checking Clang 11 with PVS-Studio Author: Andrey Karpov Date: 27.10.2020 Tags: Cpp, Compiler Every now and then, we have to write articles about how we've checked another fresh version of some compiler. That's not really much fun. However, as practice shows, if we stop doing that for a while, folks start doubting whether PVS-Studio is worth its title of a good catcher of bugs and vulnerabilities. What if the new compiler can do that too? Sure, compilers evolve, but so does PVS-Studio – and it proves, again and again, its ability to catch bugs even in high-quality projects such as compilers. Time for rechecking Clang To tell you the truth, I wrote this article based on the earlier post "Checking the GCC 10 Compiler with PVS-Studio". So if some paragraphs seem familiar, it's because you've already read them before :). It's no secret that compilers employ their own built-in static code analyzers, and those are developing as well. That's why we write articles every now and then to show that our static analyzer, PVS-Studio, can find bugs even inside compilers and that we are worth our salt :). In fact, you can't compare classic static analyzers with compilers. Static analyzers not only detect bugs in source code but also involve a highly developed infrastructure. For one thing, it includes integration with such systems as SonarQube, PlatformIO, Azure DevOps, Travis CI, CircleCI, GitLab CI/CD, Jenkins, and Visual Studio. It includes mechanisms for mass suppression of warnings, which allows you to start using PVS-Studio right off even in a large project. It includes sending notifications by email. And so on and so forth. But the first question developers will still ask is, "Can your PVS-Studio find anything that compilers can't?" And that means we are doomed to write articles about how we check the compilers themselves over and over again. Let's get back to Clang. There's no need to dwell on the subject and tell you what the project is about. Actually, we checked not only the code of Clang 11 itself but also the code of the LLVM 11 library it's
  • 2. based on. From this article's viewpoint, it doesn't matter if a defect was found in the compiler's or the library's code. I found the code of Clang/LLVM much clearer than that of GCC. At least it's not teeming with all those awful macros and it extensively employs C++'s modern features. Even so, the project is still big enough to make examining the analysis report tedious without prior customization. What mostly gets in the way is "semi-false" positives. By "semi-false" positives I mean cases where the analyzer is technically correct to point out certain issues but those warnings are of no practical use. For example, a lot of such warnings refer to unit tests and generated code. Here's an example for unit tests: Spaces.SpacesInParentheses = false; // <= Spaces.SpacesInCStyleCastParentheses = true; // <= verifyFormat("Type *A = ( Type * )P;", Spaces); verifyFormat("Type *A = ( vector<Type *, int *> )P;", Spaces); verifyFormat("x = ( int32 )y;", Spaces); verifyFormat("int a = ( int )(2.0f);", Spaces); verifyFormat("#define AA(X) sizeof((( X * )NULL)->a)", Spaces); verifyFormat("my_int a = ( my_int )sizeof(int);", Spaces); verifyFormat("#define x (( int )-1)", Spaces); // Run the first set of tests again with: Spaces.SpacesInParentheses = false; // <= Spaces.SpaceInEmptyParentheses = true; Spaces.SpacesInCStyleCastParentheses = true; // <= verifyFormat("call(x, y, z);", Spaces); verifyFormat("call( );", Spaces); The analyzer warns us that the variables are assigned the same values they already have: • V1048 The 'Spaces.SpacesInParentheses' variable was assigned the same value. FormatTest.cpp 11554 • V1048 The 'Spaces.SpacesInCStyleCastParentheses' variable was assigned the same value. FormatTest.cpp 11556 Technically, this warning is to the point and the snippet needs simplifying or fixing. But it's also clear that this code is fine as it is and there's no point fixing anything in it. Here's another example: the analyzer outputs a ton of warnings on the autogenerated file Options.inc. Look at the "wall" of code it contains:
  • 3. This bulk of code triggers a flood of warnings: • V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr == nullptr Options.inc 26 • V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr == nullptr Options.inc 27 • V501 There are identical sub-expressions to the left and to the right of the '==' operator: nullptr == nullptr Options.inc 28 • and so on – one warning per line... Yet all that is not a big deal. It can be solved by excluding irrelevant files from analysis, marking certain macros and functions, suppressing certain diagnostic types, and so on. Yes, it can, but it's not a very interesting job to do when you write an article. That's why I did the same thing as in the article about checking the GCC compiler: I kept reading the report until I collected 11 interesting examples to include in the article. Why 11? I just thought that since it was the 11-th version of Clang, I needed 11 examples :). 11 suspicious code snippets Snippet 1, modulo operation on 1
  • 4. This is a cool one! I like bugs like that! void Act() override { .... // If the value type is a vector, and we allow vector select, then in 50% // of the cases generate a vector select. if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 1)) { unsigned NumElem = cast<FixedVectorType>(Val0->getType())->getNumElements(); CondTy = FixedVectorType::get(CondTy, NumElem); } .... } PVS-Studio diagnostic message: V1063 The modulo by 1 operation is meaningless. The result will always be zero. llvm-stress.cpp 631 The programmer is using a modulo operation to get a random value of either 0 or 1. But the value 1 seems to confuse developers and make them write the classic anti-pattern in which the modulo operation is performed on 1 instead of 2. The X % 1 operation is meaningless as it always evaluates to 0. This is the fixed version: if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 2)) { The recently added V1063 diagnostic is awfully simple, but, as you can see, it works perfectly. We know that compiler developers keep an eye on our work and borrow our ideas. That's totally fine. It's nice to know that PVS-Studio is the driving force behind progress. Let's see how much it will take for a similar diagnostic to appear in Clang and GCC :). Snippet 2, a typo in a condition
  • 5. class ReturnValueSlot { .... bool isNull() const { return !Addr.isValid(); } .... }; static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1, const FunctionDecl *F2, unsigned NumParams) { .... unsigned I1 = 0, I2 = 0; for (unsigned I = 0; I != NumParams; ++I) { QualType T1 = NextParam(F1, I1, I == 0); QualType T2 = NextParam(F2, I2, I == 0); if (!T1.isNull() && !T1.isNull() && !Context.hasSameUnqualifiedType(T1, T2)) return false; } return true; } PVS-Studio diagnostic message: V501 There are identical sub-expressions to the left and to the right of the '&&' operator: !T1.isNull() && !T1.isNull() SemaOverload.cpp 9493 The !T1.isNull() check is performed twice. This is obviously a typo; the second part of the condition must check the T2 variable. Snippet 3, potential array-index-out-of-bounds std::vector<Decl *> DeclsLoaded; SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) { .... unsigned Index = ID - NUM_PREDEF_DECL_IDS; if (Index > DeclsLoaded.size()) { Error("declaration ID out-of-range for AST file"); return SourceLocation(); } if (Decl *D = DeclsLoaded[Index]) return D->getLocation(); .... } PVS-Studio diagnostic message: V557 Array overrun is possible. The 'Index' index is pointing beyond array bound. ASTReader.cpp 7318 Suppose the array stores one element and the value of the Index variable is also 1. Then the (1 > 1) condition is false, and, therefore, the array will be indexed beyond its bounds. Here's the correct check: if (Index >= DeclsLoaded.size()) { Snippet 4, argument evaluation order void IHexELFBuilder::addDataSections() { .... uint32_t SecNo = 1; .... Section = &Obj->addSection<OwnedDataSection>( ".sec" + std::to_string(SecNo++), RecAddr, ELF::SHF_ALLOC | ELF::SHF_WRITE, SecNo); ....
  • 6. } PVS-Studio diagnostic message: V567 Unspecified behavior. The order of argument evaluation is not defined for 'addSection' function. Consider inspecting the 'SecNo' variable. Object.cpp 1223 Note that the SecNo argument is used twice, getting incremented in the meanwhile. The problem is, you can't tell in what exact order the arguments will be evaluated. The result will, therefore, vary depending on the compiler version or compilation parameters. Here's a synthetic example to illustrate this point: #include <cstdio> int main() { int i = 1; printf("%d, %dn", i, i++); return 0; } Depending on the compiler, this code may output either "1, 1" or "2, 1". I ran it on Compiler Explorer and got the following outputs: • when compiled with Clang 11.0.0, the program outputs 1, 1. • when compiled with GCC 10.2, the program outputs 2, 1. Interestingly, this simple case causes Clang to issue a warning: <source>:6:26: warning: unsequenced modification and access to 'i' [-Wunsequenced] printf("%d, %dn", i, i++); For some reason, though, this warning wasn't issued on the real code. Either it's disabled as a not very practical one or that case is too complicated for the compiler to cope with. Snippet 5, a strange duplicate check template <class ELFT> void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj, const Elf_Shdr *Sec) { .... Expected<StringRef> NameOrErr = this->dumper()->getSymbolVersionByIndex(Ndx, IsDefault); if (!NameOrErr) { if (!NameOrErr) { unsigned SecNdx = Sec - &cantFail(Obj->sections()).front(); this->reportUniqueWarning(createError( "unable to get a version for entry " + Twine(I) + " of SHT_GNU_versym section with index " + Twine(SecNdx) + ": " + toString(NameOrErr.takeError()))); } Versions.emplace_back("<corrupt>"); continue; } .... } PVS-Studio diagnostic message: V571 Recurring check. The 'if (!NameOrErr)' condition was already verified in line 4666. ELFDumper.cpp 4667
  • 7. The second check is a clone of the first and is, therefore, redundant. Maybe it could be safely removed. But what's more likely is that it contains a typo and was meant to check some other variable. Snippet 6, potential null pointer dereference void RewriteObjCFragileABI::RewriteObjCClassMetaData( ObjCImplementationDecl *IDecl, std::string &Result) { ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); if (CDecl->isImplicitInterfaceDecl()) { RewriteObjCInternalStruct(CDecl, Result); } unsigned NumIvars = !IDecl->ivar_empty() ? IDecl->ivar_size() : (CDecl ? CDecl->ivar_size() : 0); .... } PVS-Studio diagnostic message: V595 The 'CDecl' pointer was utilized before it was verified against nullptr. Check lines: 5275, 5284. RewriteObjC.cpp 5275 When performing the first check, the developer never hesitates to dereference the CDecl pointer: if (CDecl->isImplicitInterfaceDecl()) But if you look at the code a few lines further, it becomes clear that the pointer can be null: (CDecl ? CDecl->ivar_size() : 0) The first check was probably meant to look like this: if (CDecl && CDecl->isImplicitInterfaceDecl()) Snippet 7, potential null pointer dereference bool Sema::InstantiateClass(....) { .... NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl); CXXRecordDecl *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), ND && ND->isCXXInstanceMember()); .... } PVS-Studio diagnostic message: V595 The 'ND' pointer was utilized before it was verified against nullptr. Check lines: 2803, 2805. SemaTemplateInstantiate.cpp 2803 This error is similar to the previous one. It's dangerous to dereference a pointer without a prior check when its value is acquired using a dynamic type cast. More than that, subsequent code confirms that such a check is needed. Snippet 8, a function keeping running despite an error state bool VerifyObject(llvm::yaml::Node &N, std::map<std::string, std::string> Expected) {
  • 8. .... auto *V = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getValue()); if (!V) { ADD_FAILURE() << KS << " is not a string"; Match = false; } std::string VS = V->getValue(Tmp).str(); .... } PVS-Studio diagnostic message: V1004 The 'V' pointer was used unsafely after it was verified against nullptr. Check lines: 61, 65. TraceTests.cpp 65 The V pointer may be a null pointer. This is obviously an error state, which is even reported with an error message. But the function will just keep running as if nothing happened and will end up dereferencing that very null pointer. The programmer probably wanted the function to stop at this point, in which case it should be fixed as follows: auto *V = llvm::dyn_cast_or_null<llvm::yaml::ScalarNode>(Prop.getValue()); if (!V) { ADD_FAILURE() << KS << " is not a string"; Match = false; return false; } std::string VS = V->getValue(Tmp).str(); Snippet 9, a typo const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input, const InputInfo &Output) { if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ)) if (StringRef(A->getValue()) == "single") return Args.MakeArgString(Output.getFilename()); Arg *FinalOutput = Args.getLastArg(options::OPT_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { SmallString<128> T(FinalOutput->getValue()); llvm::sys::path::replace_extension(T, "dwo"); return Args.MakeArgString(T); } else { // Use the compilation dir. SmallString<128> T( Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput())); llvm::sys::path::replace_extension(F, "dwo"); T += F; return Args.MakeArgString(F); // <= } } PVS-Studio diagnostic message: V1001 The 'T' variable is assigned but is not used by the end of the function. CommonArgs.cpp 873 Look at the last lines of the function. The local variable T changes but isn't used in any way. This must be a typo and the function should probably end as follows: T += F; return Args.MakeArgString(T); Snippet 10, zero as the divisor typedef int32_t si_int;
  • 9. typedef uint32_t su_int; typedef union { du_int all; struct { #if _YUGA_LITTLE_ENDIAN su_int low; su_int high; #else su_int high; su_int low; #endif // _YUGA_LITTLE_ENDIAN } s; } udwords; COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { .... if (d.s.low == 0) { if (d.s.high == 0) { // K X // --- // 0 0 if (rem) *rem = n.s.high % d.s.low; return n.s.high / d.s.low; } .... } PVS-Studio diagnostic messages: • V609 Mod by zero. Denominator 'd.s.low' == 0. udivmoddi4.c 61 • V609 Divide by zero. Denominator 'd.s.low' == 0. udivmoddi4.c 62 I don't know if this is a bug or some tricky contraption, but the code does look strange. It has two regular integer variables, one of which is divided by the other. But the interesting part is that the division operation takes place only if both variables are zeroes. What task is it supposed to accomplish? Snippet 11, copy-paste bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(....) { .... StringRef FName = II->getName(); .... if (FName == "postEvent" && FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") { return true; } if (FName == "postEvent" && FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") { return true; } .... }
  • 10. PVS-Studio diagnostic message: V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 3108, 3113. MallocChecker.cpp 3113 A code fragment was cloned but never modified afterwards. This clone should either be removed or modified to perform some useful check. Conclusion {{GET_TRIAL_INSERT}} Remember that you can use this free-license option to check open-source projects. We provide other ways to use PVS-Studio for free as well, some of them even allowing analysis of proprietary code. See the full list of options here: "Ways to Get a Free PVS-Studio License". Thank you for reading! Further reading on checking compilers with PVS-Studio 1. Check of LLVM (Clang) (August 2011), second check (August 2012), third check (October 2016), fourth check (April 2019) 2. Check of GCC (August 2016), second check (April 2020) 3. Check of Huawei Ark Compiler (December 2019) 4. Check of .NET Compiler Platform ("Roslyn") (December 2015), second check (April 2019) 5. Check of Roslyn Analyzers (August 2019) 6. Check of PascalABC.NET (March 2017)