SlideShare a Scribd company logo
1 of 5
Download to read offline
Static	analysis	should	be	used	regularly
Author: Andrey Karpov
Date: 20.08.2012
We have a practice of occasionally re-analyzing projects we have already checked with PVS-Studio. There
are several reasons why we do so. For example, we want to know if we have managed to eliminate false
positives for certain diagnostics. But the most interesting thing is to see how new diagnostic rules work and
what errors they can find. It is very interesting to watch the tool catch more and more new defects in a
project that seems to be cleaned out already. The next project we have re-checked is Clang.
Clang is a project of great interest to us. First, because it's very high-quality. It means that finding a new
error in it is a large achievement. Second, because it shows very clear various faults in PVS-Studio which
cause false positives.
Unfortunately, more than a month has passed since the recheck and writing of this article. My vacation was
the reason. It's probable that the suspicious code described here is already fixed by the moment of
publication of this post. But it's OK. The main thing is that I can remind the readers that static analysis is a
tool to be used regularly, not from time to time.
Static analysis should be applied regularly, as:
• New code is added into a project. If you don't check it at once, many errors will take much time to
fix. They will be reported by the testing department or your customers.
• Tools learn to catch more and more error patterns.
All this sounds very simple and even trivial. Unfortunately, developers are lazy to integrate static analysis
into the development process. We have to nudge them to make this step again and again.
The previous check of the Clang project was carried out about one year ago. We have added new diagnostic
rules during this time that helped us to detect new suspicious code fragments. They are not numerous,
though. It's no wonder because the Clang project contains a static analyzer itself and is developed by highly-
skilled programmers. It's just strange that we manage to find something at all.
Let's see what interesting issues we have managed to find in the code. Suspicious fragments are mostly
related to shift operations.
int64_t DataExtractor::getSLEB128(....) const {
int64_t result = 0;
...
// Sign bit of byte is 2nd high order bit (0x40)
if (shift < 64 && (byte & 0x40))
result |= -(1 << shift);
...
}
PVS-Studio: V629 Consider inspecting the '1 << shift' expression. Bit shifting of the 32-bit value with a
subsequent expansion to the 64-bit type. dataextractor.cpp 171
Judging by the "shift < 64" check, value 1 can be shifted to the left by [0..63] bits. But this code may lead to
undefined behavior. See the article "Wade not in unknown waters. Part three" to learn more about the
reasons why undefined behavior may occur here. What is tricky about such defects is that your program
might pretend to work correctly for a long time. Faults occur when you switch to another compiler version,
start using a different optimization switch and after code refactoring.
The code will become safe if number 1 is represented by a 64-bit unsigned data type. In this case you can
safely shift it by 63 bits. This is the safe code:
result |= -(1ui64 << shift);
Unfortunately, I'm not sure what to do with the minus sign.
Consider another sample containing a strange shift operation:
void EmitVBR64(uint64_t Val, unsigned NumBits) {
if ((uint32_t)Val == Val)
return EmitVBR((uint32_t)Val, NumBits);
uint64_t Threshold = 1U << (NumBits-1);
...
}
PVS-Studio: V629 Consider inspecting the '1U << (NumBits - 1)' expression. Bit shifting of the 32-bit value
with a subsequent expansion to the 64-bit type. bitstreamwriter.h 173
If the 'NumBits' argument can be larger than 32, the function will work incorrectly. Like in the previous
example, undefined behavior will occur when '1U' is shifted by many bits. In practice, undefined behavior
will most probably manifest itself through putting meaningless values into the 'Threshold' variable.
This is the safe code:
uint64_t Threshold = 1UI64 << (NumBits-1);
The samples described above will cause errors only if there is a shift by a large number of bits. But there are
fragments that cause undefined behavior all the time. For example, such is a negative number shift.
int find_next(unsigned Prev) const {
...
// Mask off previous bits.
Copy &= ~0L << BitPos;
...
}
PVS-Studio: V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative.
bitvector.h 175
This code is not safe. The Clang project is built for various platforms. That's why you need to be careful
when using such constructs. It's difficult to predict consequences of negative number shifts on certain
platforms.
There are other potentially dangerous shift operations as well. They are all alike, so we won't consider them
in detail. Let me just list them according to their location in the code:
• V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative.
pointerintpair.h 139
• V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative.
bitvector.h 454
• V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative.
sparsebitvector.h 161
• V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative.
pointerintpair.h 144
• V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative.
densemapinfo.h 35
• V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative.
densemapinfo.h 40
• V629 Consider inspecting the '1U << (NumBits - 1)' expression. Bit shifting of the 32-bit value with a
subsequent expansion to the 64-bit type. bitstreamreader.h 362
• V629 Consider inspecting the 'Bit->getValue() << i' expression. Bit shifting of the 32-bit value with a
subsequent expansion to the 64-bit type. record.cpp 248
Besides strange shifts we have found several strange loops. The point is that they iterate only once.
bool ObjCARCOpt::VisitBottomUp(....) {
...
for (BBState::edge_iterator SI(MyStates.succ_begin()),
SE(MyStates.succ_end()); SI != SE; ++SI)
{
const BasicBlock *Succ = *SI;
DenseMap<const BasicBlock *, BBState>::iterator I =
BBStates.find(Succ);
assert(I != BBStates.end());
MyStates.InitFromSucc(I->second);
++SI;
for (; SI != SE; ++SI) {
Succ = *SI;
I = BBStates.find(Succ);
assert(I != BBStates.end());
MyStates.MergeSucc(I->second);
}
break;
}
...
}
PVS-Studio: V612 An unconditional 'break' within a loop. objcarc.cpp 2763
Note the last 'break' operator. There is no condition before it and it always finishes the loop. So, the loop
iterates only once.
These are similar strange code fragments:
• V612 An unconditional 'break' within a loop. objcarc.cpp 2948
• V612 An unconditional 'break' within a loop. undefinedassignmentchecker.cpp 75
• V612 An unconditional 'break' within a loop. bugreporter.cpp 1095
Conclusion
The V610, V612, V629 diagnostics are new and therefore allowed us to find some new interesting bugs. If
you have checked your project a year ago, it doesn't matter. It doesn't matter at all. Because you have
written a new unchecked code. The analyzer has also got new diagnostic capabilities. They actually continue
appearing each month. Start using static analysis regularly and you will spend quite fewer efforts searching
for and eliminating a great many of errors.

More Related Content

What's hot

What's hot (19)

Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4
 
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
 
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
 
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
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More Time
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
Streams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to RxStreams, Streams Everywhere! An Introduction to Rx
Streams, Streams Everywhere! An Introduction to Rx
 
Checking VirtualDub
Checking VirtualDubChecking VirtualDub
Checking VirtualDub
 
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 Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
A Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatA Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCat
 
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
 
RxJava@Android
RxJava@AndroidRxJava@Android
RxJava@Android
 
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerRechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
 
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
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
Intro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich AndroidIntro to RxJava/RxAndroid - GDG Munich Android
Intro to RxJava/RxAndroid - GDG Munich Android
 
Copy-Paste and Muons
Copy-Paste and MuonsCopy-Paste and Muons
Copy-Paste and Muons
 

Viewers also liked

Viewers also liked (20)

What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!
 
Visual C++ project model
Visual C++ project modelVisual C++ project model
Visual C++ project model
 
Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...
 
Errors detected in C++Builder
Errors detected in C++BuilderErrors detected in C++Builder
Errors detected in C++Builder
 
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ codePVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
 
The D language comes to help
The D language comes to helpThe D language comes to help
The D language comes to help
 
Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.
 
Visual Studio tool windows
Visual Studio tool windowsVisual Studio tool windows
Visual Studio tool windows
 
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
 
What comments hide
What comments hideWhat comments hide
What comments hide
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.
 
Software diseases: memset
Software diseases: memsetSoftware diseases: memset
Software diseases: memset
 
100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?
 
Difficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usabilityDifficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usability
 
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-StudioComparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
 
Cppcheck
CppcheckCppcheck
Cppcheck
 
Leo Tolstoy and static code analysis
Leo Tolstoy and static code analysisLeo Tolstoy and static code analysis
Leo Tolstoy and static code analysis
 
Studying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's websiteStudying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's website
 
An ideal static analyzer, or why ideals are unachievable
An ideal static analyzer, or why ideals are unachievableAn ideal static analyzer, or why ideals are unachievable
An ideal static analyzer, or why ideals are unachievable
 

Similar to Static analysis should be used regularly

Similar to Static analysis should be used regularly (20)

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
 
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
 
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
 
Linux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLiteLinux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLite
 
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
 
Checking PVS-Studio with Clang
Checking PVS-Studio with ClangChecking PVS-Studio with Clang
Checking PVS-Studio with Clang
 
PVS-Studio team is about to produce a technical breakthrough, but for now let...
PVS-Studio team is about to produce a technical breakthrough, but for now let...PVS-Studio team is about to produce a technical breakthrough, but for now let...
PVS-Studio team is about to produce a technical breakthrough, but for now let...
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
SAST, fight against potential vulnerabilities
SAST, fight against potential vulnerabilitiesSAST, fight against potential vulnerabilities
SAST, fight against potential vulnerabilities
 
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
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
Analysis of PascalABC.NET using SonarQube plugins: SonarC# and PVS-Studio
Analysis of PascalABC.NET using SonarQube plugins: SonarC# and PVS-StudioAnalysis of PascalABC.NET using SonarQube plugins: SonarC# and PVS-Studio
Analysis of PascalABC.NET using SonarQube plugins: SonarC# and PVS-Studio
 
A Long-Awaited Check of Unreal Engine 4
A Long-Awaited Check of Unreal Engine 4A Long-Awaited Check of Unreal Engine 4
A Long-Awaited Check of Unreal Engine 4
 
PVS-Studio for Linux Went on a Tour Around Disney
PVS-Studio for Linux Went on a Tour Around DisneyPVS-Studio for Linux Went on a Tour Around Disney
PVS-Studio for Linux Went on a Tour Around Disney
 
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
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 
Analyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-StudioAnalyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-Studio
 
I just had to check ICQ project
I just had to check ICQ projectI just had to check ICQ project
I just had to check ICQ project
 
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
 
Wade not in unknown waters. Part three.
Wade not in unknown waters. Part three.Wade not in unknown waters. Part three.
Wade not in unknown waters. Part three.
 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 

Static analysis should be used regularly

  • 1. Static analysis should be used regularly Author: Andrey Karpov Date: 20.08.2012 We have a practice of occasionally re-analyzing projects we have already checked with PVS-Studio. There are several reasons why we do so. For example, we want to know if we have managed to eliminate false positives for certain diagnostics. But the most interesting thing is to see how new diagnostic rules work and what errors they can find. It is very interesting to watch the tool catch more and more new defects in a project that seems to be cleaned out already. The next project we have re-checked is Clang. Clang is a project of great interest to us. First, because it's very high-quality. It means that finding a new error in it is a large achievement. Second, because it shows very clear various faults in PVS-Studio which cause false positives. Unfortunately, more than a month has passed since the recheck and writing of this article. My vacation was the reason. It's probable that the suspicious code described here is already fixed by the moment of publication of this post. But it's OK. The main thing is that I can remind the readers that static analysis is a tool to be used regularly, not from time to time. Static analysis should be applied regularly, as: • New code is added into a project. If you don't check it at once, many errors will take much time to fix. They will be reported by the testing department or your customers. • Tools learn to catch more and more error patterns. All this sounds very simple and even trivial. Unfortunately, developers are lazy to integrate static analysis into the development process. We have to nudge them to make this step again and again. The previous check of the Clang project was carried out about one year ago. We have added new diagnostic rules during this time that helped us to detect new suspicious code fragments. They are not numerous, though. It's no wonder because the Clang project contains a static analyzer itself and is developed by highly- skilled programmers. It's just strange that we manage to find something at all. Let's see what interesting issues we have managed to find in the code. Suspicious fragments are mostly related to shift operations. int64_t DataExtractor::getSLEB128(....) const { int64_t result = 0; ... // Sign bit of byte is 2nd high order bit (0x40) if (shift < 64 && (byte & 0x40))
  • 2. result |= -(1 << shift); ... } PVS-Studio: V629 Consider inspecting the '1 << shift' expression. Bit shifting of the 32-bit value with a subsequent expansion to the 64-bit type. dataextractor.cpp 171 Judging by the "shift < 64" check, value 1 can be shifted to the left by [0..63] bits. But this code may lead to undefined behavior. See the article "Wade not in unknown waters. Part three" to learn more about the reasons why undefined behavior may occur here. What is tricky about such defects is that your program might pretend to work correctly for a long time. Faults occur when you switch to another compiler version, start using a different optimization switch and after code refactoring. The code will become safe if number 1 is represented by a 64-bit unsigned data type. In this case you can safely shift it by 63 bits. This is the safe code: result |= -(1ui64 << shift); Unfortunately, I'm not sure what to do with the minus sign. Consider another sample containing a strange shift operation: void EmitVBR64(uint64_t Val, unsigned NumBits) { if ((uint32_t)Val == Val) return EmitVBR((uint32_t)Val, NumBits); uint64_t Threshold = 1U << (NumBits-1); ... } PVS-Studio: V629 Consider inspecting the '1U << (NumBits - 1)' expression. Bit shifting of the 32-bit value with a subsequent expansion to the 64-bit type. bitstreamwriter.h 173 If the 'NumBits' argument can be larger than 32, the function will work incorrectly. Like in the previous example, undefined behavior will occur when '1U' is shifted by many bits. In practice, undefined behavior will most probably manifest itself through putting meaningless values into the 'Threshold' variable. This is the safe code: uint64_t Threshold = 1UI64 << (NumBits-1);
  • 3. The samples described above will cause errors only if there is a shift by a large number of bits. But there are fragments that cause undefined behavior all the time. For example, such is a negative number shift. int find_next(unsigned Prev) const { ... // Mask off previous bits. Copy &= ~0L << BitPos; ... } PVS-Studio: V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative. bitvector.h 175 This code is not safe. The Clang project is built for various platforms. That's why you need to be careful when using such constructs. It's difficult to predict consequences of negative number shifts on certain platforms. There are other potentially dangerous shift operations as well. They are all alike, so we won't consider them in detail. Let me just list them according to their location in the code: • V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative. pointerintpair.h 139 • V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative. bitvector.h 454 • V610 Undefined behavior. Check the shift operator '<<. The left operand '~0L' is negative. sparsebitvector.h 161 • V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative. pointerintpair.h 144 • V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative. densemapinfo.h 35 • V610 Undefined behavior. Check the shift operator '<<=. The left operand 'Val' is negative. densemapinfo.h 40 • V629 Consider inspecting the '1U << (NumBits - 1)' expression. Bit shifting of the 32-bit value with a subsequent expansion to the 64-bit type. bitstreamreader.h 362 • V629 Consider inspecting the 'Bit->getValue() << i' expression. Bit shifting of the 32-bit value with a subsequent expansion to the 64-bit type. record.cpp 248 Besides strange shifts we have found several strange loops. The point is that they iterate only once. bool ObjCARCOpt::VisitBottomUp(....) { ...
  • 4. for (BBState::edge_iterator SI(MyStates.succ_begin()), SE(MyStates.succ_end()); SI != SE; ++SI) { const BasicBlock *Succ = *SI; DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Succ); assert(I != BBStates.end()); MyStates.InitFromSucc(I->second); ++SI; for (; SI != SE; ++SI) { Succ = *SI; I = BBStates.find(Succ); assert(I != BBStates.end()); MyStates.MergeSucc(I->second); } break; } ... } PVS-Studio: V612 An unconditional 'break' within a loop. objcarc.cpp 2763 Note the last 'break' operator. There is no condition before it and it always finishes the loop. So, the loop iterates only once. These are similar strange code fragments: • V612 An unconditional 'break' within a loop. objcarc.cpp 2948 • V612 An unconditional 'break' within a loop. undefinedassignmentchecker.cpp 75 • V612 An unconditional 'break' within a loop. bugreporter.cpp 1095 Conclusion The V610, V612, V629 diagnostics are new and therefore allowed us to find some new interesting bugs. If you have checked your project a year ago, it doesn't matter. It doesn't matter at all. Because you have
  • 5. written a new unchecked code. The analyzer has also got new diagnostic capabilities. They actually continue appearing each month. Start using static analysis regularly and you will spend quite fewer efforts searching for and eliminating a great many of errors.