SlideShare una empresa de Scribd logo
1 de 10
Descargar para leer sin conexión
Checking	WinMerge	with	PVS-Studio	for	
the	second	time
Author: Andrey Karpov
Date: 28.03.2012
The article continues the idea that static code analyzers are tools to be used regularly, not once.
Introduction
The PVS-Studio analyzer allows you to detect errors in C/C++ applications. We checked the WinMerge
with it some time ago. There were few errors whose description can be found in the article "Comparing
the general static analysis in Visual Studio 2010 and PVS-Studio by examples of errors detected in five
open source projects" [1].
A year has passed since then, and we have decided to test the new version of WinMerge with the new
version of PVS-Studio. Below are the results of this second check. But what is the most important, there
is the following conclusion to draw from it:
There is no sense in checking a project with a static code analysis tool only once and get satisfied with
it. Analysis should be performed regularly.
These are the reasons:
1) Every new analyzer's version usually contains new diagnostic rules, which means that you can
detect more errors.
2) New errors appear in the program while writing new code. The cheapest way to detect many of
them is to use static code analyzers [2].
Let's get back to the defects found in the code. Note that many of the errors described here refer not to
the WinMerge project itself but the libraries it uses. However, it doesn't matter. We just wanted to
show that the PVS-Studio analyzer is quickly developing and learning to detect more new types of bugs.
The examples below prove it.
Fragments of odd code
Fragment N1
BOOL CCrystalEditView::
DoDropText (....)
{
...
UINT cbData = (UINT) ::GlobalSize (hData);
UINT cchText = cbData / sizeof(TCHAR) - 1;
if (cchText < 0)
return FALSE;
...
}
PVS-Studio's diagnostic rule: V547 Expression 'cchText < 0' is always false. Unsigned type value is never <
0. Merge ccrystaleditview.cpp 1135
The GlobalSize() function returns value 0 in case of an error. If it happens, this case will be handled
incorrectly. The code is built using unsigned data types, the 'cchText' variable also being of the
'unsigned' type. It means that the "cchText < 0" condition is always false. The code can be fixed by
rewriting it in the following way:
UINT cbData = (UINT) ::GlobalSize (hData);
if (cbData < sizeof(TCHAR))
return FALSE;
UINT cchText = cbData / sizeof(TCHAR) - 1;
Fragment N2
bool isopenbrace (TCHAR c)
{
return c == _T ('{') || c == _T ('(') ||
c == _T ('[') || c == _T ('<');
}
bool isclosebrace (TCHAR c)
{
return c == _T ('}') || c == _T ('}') ||
c == _T (']') || c == _T ('>');
}
PVS-Studio's diagnostic rule: V501 There are identical sub-expressions to the left and to the right of the
'||' operator: c == L'}' || c == L'}' Merge ccrystaleditview.cpp 1556
In the isclosebrace() function, the 'c' variable is compared to the '}' character twice. If you examine the
isopenbrace() function's code, you'll understand that the 'c' variable should be compared with the ')'
character in the second case.
Fragment N3
static HRESULT safeInvokeA(....)
{
HRESULT h;
...
// set h to FAILED
h = -1;
...
}
PVS-Studio's diagnostic rule: V543 It is odd that value '-1' is assigned to the variable 'h' of HRESULT type.
Merge plugins.cpp 992
It's not nice and correct to assign value -1 to a variable whose type is HRESULT.
HRESULT is a 32-bit value divided into three different fields: severity code, device code and error code.
To handle the HRESULT value, such specific constants are used as S_OK, E_FAIL, E_ABORT, etc., while
macros like SUCCEEDED and FAILED are used to check values of the HRESULT type.
The way the value "-1" is written is incorrect. If you want to report some odd bug, you should use value
0x80004005L (Unspecified failure). This constant and others similar to it are described in "WinError.h".
A similar error can be found here:
V543 It is odd that value '-1' is assigned to the variable 'h' of HRESULT type. Merge plugins.cpp 1033
Fragment N4
int TimeSizeCompare::CompareFiles(....)
{
UINT code = DIFFCODE::SAME;
...
if (di.left.size != di.right.size)
{
code &= ~DIFFCODE::SAME;
code = DIFFCODE::DIFF;
}
...
}
PVS-Studio's diagnostic rule: V519 The 'code' variable is assigned values twice successively. Perhaps this
is a mistake. Check lines: 79, 80. Merge timesizecompare.cpp 80
This code may be both correct and incorrect: since I'm not familiar with the structure of the WinMerge
project, I cannot know for sure.
Variants are possible:
1) The code contains an error, so the second line should look like this: "code |= DIFFCODE::DIFF;".
2) The code is correct. The first line is unnecessary.
Fragment N5
BOOL CEditDropTargetImpl::
OnDrop (....)
{
bool bDataSupported = false;
m_pOwner->HideDropIndicator ();
if ((!m_pOwner) ||
(!(m_pOwner->QueryEditable ())) ||
(m_pOwner->GetDisableDragAndDrop ()))
...
}
PVS-Studio's diagnostic rule: V595 The 'm_pOwner' pointer was utilized before it was verified against
nullptr. Check lines: 1033, 1035. Merge ccrystaleditview.cpp 1033
As you can see from the "if ((!m_pOwner) ....)" condition, the 'm_pOwner' pointer can be equal to zero.
But before the check is performed, this pointer is already being used in the 'm_pOwner-
>HideDropIndicator()' statement. Thus, a segmentation fault occurs instead of normal null pointer
processing.
Fragment N6
BCMenu *BCMenu::FindMenuOption(int nId, UINT& nLoc)
{
...
nLoc = -1;
...
}
BOOL BCMenu::ModifyODMenuW(....)
{
UINT nLoc;
...
BCMenu *psubmenu = FindMenuOption(nID,nLoc);
...
if (psubmenu && nLoc>=0)
mdata = psubmenu->m_MenuList[nLoc];
...
}
PVS-Studio's diagnostic rule: V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >=
0. Merge bcmenu.cpp 1232
In particular conditions, the FindMenuOption() function returns value -1 in the 'nLoc' variable. Since the
'nLoc' variable is unsigned, the function will actually return 0xFFFFFFFFu.
Now consider the code of the ModifyODMenuW() function. The "nLoc>=0" condition is always true. It
means that the situation when the FindMenuOption() function returns -1 will be processed incorrectly.
Identical errors:
V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1263
V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1285
V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1309
V547 Expression 'loc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1561
V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 2409
Fragment N7
The program contains the CompareOptions class that has virtual methods but doesn't have a virtual
destructor. Other classes, like DiffutilsOptions, inherit from it. So, absence of a virtual destructor is an
error, though it might not lead to a catastrophe.
PVS-Studio's diagnostic rule: V599 The virtual destructor is not present, although the 'CompareOptions'
class contains virtual functions. Merge diffcontext.cpp 90
It's unreasonable to cite the corresponding code fragments here because they are large.
Note that the PVS-Studio analyzer's diagnostics is rather exact and the tool doesn't swear at each and all
classes which lack a virtual destructor. If you want to understand how the analyzer diagnoses this type
of errors, see its description: V599. The virtual destructor is not present, although the 'Foo' class
contains virtual functions.
Fragment N8
static void StoreDiffData(....)
{
...
GetLog()->Write
(
CLogFile::LCOMPAREDATA,
_T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"),
di.left.filename.c_str(),
di.left.path.c_str(),
di.right.path.c_str(), di.diffcode
);
pCtxt->m_pCompareStats->AddItem(di.diffcode.diffcode);
...
}
PVS-Studio's diagnostic rule: V510 The 'Write' function is not expected to receive class-type variable as
sixth actual argument. Merge dirscan.cpp 565
The 'di.diffcode' variable is a structure of the DIFFCODE type. Most likely, the correct code was meant to
be the following:
CLogFile::LCOMPAREDATA, _T(...., di.diffcode.diffcode);
Fragment N9
static DIFFITEM *AddToList(....,
const DirItem * lent, const DirItem * rent,
....)
{
...
if (lent)
{
...
}
else
{
di->left.filename = rent->filename;
}
if (rent)
{
...
}
PVS-Studio's diagnostic rule: V595 The 'rent' pointer was utilized before it was verified against nullptr.
Check lines: 608, 611. Merge dirscan.cpp 608
The 'rent' pointer is used without checking if it's not equal to zero. Perhaps such a case will never occur
in practice. But still, the check "if (rent)" hints that it is possible in theory.
Fragment N10
String FileFilterHelper::ParseExtensions(....) const
{
String strParsed;
String strPattern;
...
strParsed = _T("^");
strPattern = string_makelower(strPattern);
strParsed = strPattern;
...
}
PVS-Studio's diagnostic rule: V519 The 'strParsed' variable is assigned values twice successively. Perhaps
this is a mistake. Check lines: 339, 342. Merge filefilterhelper.cpp 342
The 'strParsed' variable is assigned different values twice in a row. This code either has an error or an
extra assignment. A similar case has been discussed a bit earlier.
Fragment N11
void CLogFile::EnableLogging(BOOL bEnable)
{
...
Write(_T("Path: %sn*******n"), m_strLogPath);
...
}
PVS-Studio's diagnostic rule: V510 The 'Write' function is not expected to receive class-type variable as
second actual argument. Merge logfile.cpp 85
The 'm_strLogPath' variable has the std::wstring type. It means that the log will contain trash. This is the
correct code:
Write(_T("Path: %sn*******n"), m_strLogPath.c_str());
Fragment N12
void CMergeDoc::Computelinediff(
CCrystalTextView * pView1, CCrystalTextView * pView2,
....)
{
...
if (pView1->GetTextBufferEol(line) !=
pView1->GetTextBufferEol(line))
...
}
PVS-Studio's diagnostic rule: V501 There are identical sub-expressions 'pView1->GetTextBufferEol(line)'
to the left and to the right of the '!=' operator. Merge mergedoclinediffs.cpp 216
The 'pView1' variable is used twice. This code, most likely, contains a misprint, so the correct code is the
following:
if (pView1->GetTextBufferEol(line) !=
pView2->GetTextBufferEol(line))
Fragment N13
void CSplashWnd::OnPaint()
{
...
String text = LoadResString(IDS_SPLASH_DEVELOPERS);
// avoid dereference of empty strings and
// the NULL termiated character
if (text.length() >= 0)
{
...
}
PVS-Studio's diagnostic rule: V547 Expression 'text.length() >= 0' is always true. Unsigned type value is
always >= 0. Merge splash.cpp 262
The check "text.length() >= 0" is meaningless. The 'String' type is 'std::wstring'. The
'std::wstring::length()' function always returns a value above or equal to 0.
Fragment N14
void CPreferencesDlg::AddPage(CPropertyPage* pPage, ....)
{
...
m_tcPages.SetItemData(hti, (DWORD)pPage);
...
}
PVS-Studio's diagnostic rule: V205 Explicit conversion of pointer type to 32-bit integer type: (DWORD)
pPage Merge preferencesdlg.cpp 200
Theoretically (but hardly in practice), an object pointed to by 'pPage' can be located outside the first
low-order Gbytes in the 64-bit application. It implies a potential danger, as the pointer is explicitly cast
to the 32-bit type 'DWORD'. This is how this code should look to be safe:
m_tcPages.SetItemData(hti, (DWORD_PTR)pPage);
Conclusion
We have found some other odd fragments in the code. But I cannot tell for sure if they contain errors.
What is the most important, the PVS-Studio analyzer's progress is evident.
If you want to download a full-fledged trial of the analyzer, please follow this link:
http://www.viva64.com/en/pvs-studio-download/. The new trial model will help you to benefit from
the analyzer without purchasing it.
If you have questions regarding this article or the analyzer, please read the post "FAQ for those who
have read our articles" [3]. You are also welcome to ask any questions by writing a letter directly to me
and my colleagues using the feedback page.
References:
1. Evgeniy Ryzhkov. Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by
examples of errors detected in five open source projects. http://www.viva64.com/en/a/0073/
2. Andrey Karpov. Leo Tolstoy and static code analysis. http://www.viva64.com/en/b/0105/
3. Andrey Karpov. FAQ for those who have read our articles. http://www.viva64.com/en/b/0132/

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

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
 
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...
 
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
 
How to avoid bugs using modern C++
How to avoid bugs using modern C++How to avoid bugs using modern C++
How to avoid bugs using modern C++
 
A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBox
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
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
 
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
 
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
 
Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
Miranda NG Project to Get the "Wild Pointers" Award (Part 1) Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
Miranda NG Project to Get the "Wild Pointers" Award (Part 1)
 
Analyzing the Dolphin-emu project
Analyzing the Dolphin-emu projectAnalyzing the Dolphin-emu project
Analyzing the Dolphin-emu project
 
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
 
Analysis of the Ultimate Toolbox project
Analysis of the Ultimate Toolbox projectAnalysis of the Ultimate Toolbox project
Analysis of the Ultimate Toolbox project
 
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
 
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...
 
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
 
Sony C#/.NET component set analysis
Sony C#/.NET component set analysisSony C#/.NET component set analysis
Sony C#/.NET component set analysis
 
Analyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL projectAnalyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL project
 
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
 

Destacado

0136 ideal static_analyzer
0136 ideal static_analyzer0136 ideal static_analyzer
0136 ideal static_analyzer
PVS-Studio
 

Destacado (19)

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.
 
0136 ideal static_analyzer
0136 ideal static_analyzer0136 ideal static_analyzer
0136 ideal static_analyzer
 
How to make fewer errors at the stage of code writing. Part N3.
How to make fewer errors at the stage of code writing. Part N3.How to make fewer errors at the stage of code writing. Part N3.
How to make fewer errors at the stage of code writing. Part N3.
 
Regular use of static code analysis in team development
Regular use of static code analysis in team developmentRegular use of static code analysis in team development
Regular use of static code analysis in team development
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
Type Conversion in C++ and C# Arithmetic Expressions
Type Conversion in C++ and C# Arithmetic ExpressionsType Conversion in C++ and C# Arithmetic Expressions
Type Conversion in C++ and C# Arithmetic Expressions
 
R&D on PVS-Studio
R&D on PVS-StudioR&D on PVS-Studio
R&D on PVS-Studio
 
64-bit
64-bit64-bit
64-bit
 
A few words about OpenSSL
A few words about OpenSSLA few words about OpenSSL
A few words about OpenSSL
 
Analysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) projectAnalysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) project
 
Monitoring a program that monitors computer networks
Monitoring a program that monitors computer networksMonitoring a program that monitors computer networks
Monitoring a program that monitors computer networks
 
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
 
How we test the code analyzer
How we test the code analyzerHow we test the code analyzer
How we test the code analyzer
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
Cppcheck and PVS-Studio compared
Cppcheck and PVS-Studio comparedCppcheck and PVS-Studio compared
Cppcheck and PVS-Studio compared
 
The compiler is to blame for everything
The compiler is to blame for everythingThe compiler is to blame for everything
The compiler is to blame for everything
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
Visual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfacesVisual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfaces
 
100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects
 

Similar a Checking WinMerge with PVS-Studio for the second time

Similar a Checking WinMerge with PVS-Studio for the second time (17)

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
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in Doxygen
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0
 
Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?
 
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
 
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
 
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
 
Analysis of the Ultimate Toolbox project
Analysis of the Ultimate Toolbox projectAnalysis of the Ultimate Toolbox project
Analysis of the Ultimate Toolbox project
 
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
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the Microcosm
 
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
 
Static Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-StudioStatic Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-Studio
 
Critical errors in CryEngine V code
Critical errors in CryEngine V codeCritical errors in CryEngine V code
Critical errors in CryEngine V code
 
LibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-StudioLibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-Studio
 
Checking the World of Warcraft CMaNGOS open source server
Checking the World of Warcraft CMaNGOS open source serverChecking the World of Warcraft CMaNGOS open source server
Checking the World of Warcraft CMaNGOS open source server
 
Serious Sam shooter anniversary - finding bugs in the code of the Serious Eng...
Serious Sam shooter anniversary - finding bugs in the code of the Serious Eng...Serious Sam shooter anniversary - finding bugs in the code of the Serious Eng...
Serious Sam shooter anniversary - finding bugs in the code of the Serious Eng...
 

Último

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
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Último (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
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
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
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 - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
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
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 

Checking WinMerge with PVS-Studio for the second time

  • 1. Checking WinMerge with PVS-Studio for the second time Author: Andrey Karpov Date: 28.03.2012 The article continues the idea that static code analyzers are tools to be used regularly, not once. Introduction The PVS-Studio analyzer allows you to detect errors in C/C++ applications. We checked the WinMerge with it some time ago. There were few errors whose description can be found in the article "Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by examples of errors detected in five open source projects" [1]. A year has passed since then, and we have decided to test the new version of WinMerge with the new version of PVS-Studio. Below are the results of this second check. But what is the most important, there is the following conclusion to draw from it: There is no sense in checking a project with a static code analysis tool only once and get satisfied with it. Analysis should be performed regularly. These are the reasons: 1) Every new analyzer's version usually contains new diagnostic rules, which means that you can detect more errors. 2) New errors appear in the program while writing new code. The cheapest way to detect many of them is to use static code analyzers [2]. Let's get back to the defects found in the code. Note that many of the errors described here refer not to the WinMerge project itself but the libraries it uses. However, it doesn't matter. We just wanted to show that the PVS-Studio analyzer is quickly developing and learning to detect more new types of bugs. The examples below prove it. Fragments of odd code Fragment N1 BOOL CCrystalEditView:: DoDropText (....) { ...
  • 2. UINT cbData = (UINT) ::GlobalSize (hData); UINT cchText = cbData / sizeof(TCHAR) - 1; if (cchText < 0) return FALSE; ... } PVS-Studio's diagnostic rule: V547 Expression 'cchText < 0' is always false. Unsigned type value is never < 0. Merge ccrystaleditview.cpp 1135 The GlobalSize() function returns value 0 in case of an error. If it happens, this case will be handled incorrectly. The code is built using unsigned data types, the 'cchText' variable also being of the 'unsigned' type. It means that the "cchText < 0" condition is always false. The code can be fixed by rewriting it in the following way: UINT cbData = (UINT) ::GlobalSize (hData); if (cbData < sizeof(TCHAR)) return FALSE; UINT cchText = cbData / sizeof(TCHAR) - 1; Fragment N2 bool isopenbrace (TCHAR c) { return c == _T ('{') || c == _T ('(') || c == _T ('[') || c == _T ('<'); } bool isclosebrace (TCHAR c) { return c == _T ('}') || c == _T ('}') || c == _T (']') || c == _T ('>'); } PVS-Studio's diagnostic rule: V501 There are identical sub-expressions to the left and to the right of the '||' operator: c == L'}' || c == L'}' Merge ccrystaleditview.cpp 1556
  • 3. In the isclosebrace() function, the 'c' variable is compared to the '}' character twice. If you examine the isopenbrace() function's code, you'll understand that the 'c' variable should be compared with the ')' character in the second case. Fragment N3 static HRESULT safeInvokeA(....) { HRESULT h; ... // set h to FAILED h = -1; ... } PVS-Studio's diagnostic rule: V543 It is odd that value '-1' is assigned to the variable 'h' of HRESULT type. Merge plugins.cpp 992 It's not nice and correct to assign value -1 to a variable whose type is HRESULT. HRESULT is a 32-bit value divided into three different fields: severity code, device code and error code. To handle the HRESULT value, such specific constants are used as S_OK, E_FAIL, E_ABORT, etc., while macros like SUCCEEDED and FAILED are used to check values of the HRESULT type. The way the value "-1" is written is incorrect. If you want to report some odd bug, you should use value 0x80004005L (Unspecified failure). This constant and others similar to it are described in "WinError.h". A similar error can be found here: V543 It is odd that value '-1' is assigned to the variable 'h' of HRESULT type. Merge plugins.cpp 1033 Fragment N4 int TimeSizeCompare::CompareFiles(....) { UINT code = DIFFCODE::SAME; ... if (di.left.size != di.right.size) { code &= ~DIFFCODE::SAME;
  • 4. code = DIFFCODE::DIFF; } ... } PVS-Studio's diagnostic rule: V519 The 'code' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 79, 80. Merge timesizecompare.cpp 80 This code may be both correct and incorrect: since I'm not familiar with the structure of the WinMerge project, I cannot know for sure. Variants are possible: 1) The code contains an error, so the second line should look like this: "code |= DIFFCODE::DIFF;". 2) The code is correct. The first line is unnecessary. Fragment N5 BOOL CEditDropTargetImpl:: OnDrop (....) { bool bDataSupported = false; m_pOwner->HideDropIndicator (); if ((!m_pOwner) || (!(m_pOwner->QueryEditable ())) || (m_pOwner->GetDisableDragAndDrop ())) ... } PVS-Studio's diagnostic rule: V595 The 'm_pOwner' pointer was utilized before it was verified against nullptr. Check lines: 1033, 1035. Merge ccrystaleditview.cpp 1033 As you can see from the "if ((!m_pOwner) ....)" condition, the 'm_pOwner' pointer can be equal to zero. But before the check is performed, this pointer is already being used in the 'm_pOwner- >HideDropIndicator()' statement. Thus, a segmentation fault occurs instead of normal null pointer processing.
  • 5. Fragment N6 BCMenu *BCMenu::FindMenuOption(int nId, UINT& nLoc) { ... nLoc = -1; ... } BOOL BCMenu::ModifyODMenuW(....) { UINT nLoc; ... BCMenu *psubmenu = FindMenuOption(nID,nLoc); ... if (psubmenu && nLoc>=0) mdata = psubmenu->m_MenuList[nLoc]; ... } PVS-Studio's diagnostic rule: V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1232 In particular conditions, the FindMenuOption() function returns value -1 in the 'nLoc' variable. Since the 'nLoc' variable is unsigned, the function will actually return 0xFFFFFFFFu. Now consider the code of the ModifyODMenuW() function. The "nLoc>=0" condition is always true. It means that the situation when the FindMenuOption() function returns -1 will be processed incorrectly. Identical errors: V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1263 V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1285 V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1309 V547 Expression 'loc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 1561 V547 Expression 'nLoc >= 0' is always true. Unsigned type value is always >= 0. Merge bcmenu.cpp 2409
  • 6. Fragment N7 The program contains the CompareOptions class that has virtual methods but doesn't have a virtual destructor. Other classes, like DiffutilsOptions, inherit from it. So, absence of a virtual destructor is an error, though it might not lead to a catastrophe. PVS-Studio's diagnostic rule: V599 The virtual destructor is not present, although the 'CompareOptions' class contains virtual functions. Merge diffcontext.cpp 90 It's unreasonable to cite the corresponding code fragments here because they are large. Note that the PVS-Studio analyzer's diagnostics is rather exact and the tool doesn't swear at each and all classes which lack a virtual destructor. If you want to understand how the analyzer diagnoses this type of errors, see its description: V599. The virtual destructor is not present, although the 'Foo' class contains virtual functions. Fragment N8 static void StoreDiffData(....) { ... GetLog()->Write ( CLogFile::LCOMPAREDATA, _T("name=<%s>, leftdir=<%s>, rightdir=<%s>, code=%d"), di.left.filename.c_str(), di.left.path.c_str(), di.right.path.c_str(), di.diffcode ); pCtxt->m_pCompareStats->AddItem(di.diffcode.diffcode); ... } PVS-Studio's diagnostic rule: V510 The 'Write' function is not expected to receive class-type variable as sixth actual argument. Merge dirscan.cpp 565 The 'di.diffcode' variable is a structure of the DIFFCODE type. Most likely, the correct code was meant to be the following: CLogFile::LCOMPAREDATA, _T(...., di.diffcode.diffcode);
  • 7. Fragment N9 static DIFFITEM *AddToList(...., const DirItem * lent, const DirItem * rent, ....) { ... if (lent) { ... } else { di->left.filename = rent->filename; } if (rent) { ... } PVS-Studio's diagnostic rule: V595 The 'rent' pointer was utilized before it was verified against nullptr. Check lines: 608, 611. Merge dirscan.cpp 608 The 'rent' pointer is used without checking if it's not equal to zero. Perhaps such a case will never occur in practice. But still, the check "if (rent)" hints that it is possible in theory. Fragment N10 String FileFilterHelper::ParseExtensions(....) const { String strParsed; String strPattern; ...
  • 8. strParsed = _T("^"); strPattern = string_makelower(strPattern); strParsed = strPattern; ... } PVS-Studio's diagnostic rule: V519 The 'strParsed' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 339, 342. Merge filefilterhelper.cpp 342 The 'strParsed' variable is assigned different values twice in a row. This code either has an error or an extra assignment. A similar case has been discussed a bit earlier. Fragment N11 void CLogFile::EnableLogging(BOOL bEnable) { ... Write(_T("Path: %sn*******n"), m_strLogPath); ... } PVS-Studio's diagnostic rule: V510 The 'Write' function is not expected to receive class-type variable as second actual argument. Merge logfile.cpp 85 The 'm_strLogPath' variable has the std::wstring type. It means that the log will contain trash. This is the correct code: Write(_T("Path: %sn*******n"), m_strLogPath.c_str()); Fragment N12 void CMergeDoc::Computelinediff( CCrystalTextView * pView1, CCrystalTextView * pView2, ....) { ... if (pView1->GetTextBufferEol(line) != pView1->GetTextBufferEol(line))
  • 9. ... } PVS-Studio's diagnostic rule: V501 There are identical sub-expressions 'pView1->GetTextBufferEol(line)' to the left and to the right of the '!=' operator. Merge mergedoclinediffs.cpp 216 The 'pView1' variable is used twice. This code, most likely, contains a misprint, so the correct code is the following: if (pView1->GetTextBufferEol(line) != pView2->GetTextBufferEol(line)) Fragment N13 void CSplashWnd::OnPaint() { ... String text = LoadResString(IDS_SPLASH_DEVELOPERS); // avoid dereference of empty strings and // the NULL termiated character if (text.length() >= 0) { ... } PVS-Studio's diagnostic rule: V547 Expression 'text.length() >= 0' is always true. Unsigned type value is always >= 0. Merge splash.cpp 262 The check "text.length() >= 0" is meaningless. The 'String' type is 'std::wstring'. The 'std::wstring::length()' function always returns a value above or equal to 0. Fragment N14 void CPreferencesDlg::AddPage(CPropertyPage* pPage, ....) { ... m_tcPages.SetItemData(hti, (DWORD)pPage);
  • 10. ... } PVS-Studio's diagnostic rule: V205 Explicit conversion of pointer type to 32-bit integer type: (DWORD) pPage Merge preferencesdlg.cpp 200 Theoretically (but hardly in practice), an object pointed to by 'pPage' can be located outside the first low-order Gbytes in the 64-bit application. It implies a potential danger, as the pointer is explicitly cast to the 32-bit type 'DWORD'. This is how this code should look to be safe: m_tcPages.SetItemData(hti, (DWORD_PTR)pPage); Conclusion We have found some other odd fragments in the code. But I cannot tell for sure if they contain errors. What is the most important, the PVS-Studio analyzer's progress is evident. If you want to download a full-fledged trial of the analyzer, please follow this link: http://www.viva64.com/en/pvs-studio-download/. The new trial model will help you to benefit from the analyzer without purchasing it. If you have questions regarding this article or the analyzer, please read the post "FAQ for those who have read our articles" [3]. You are also welcome to ask any questions by writing a letter directly to me and my colleagues using the feedback page. References: 1. Evgeniy Ryzhkov. Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by examples of errors detected in five open source projects. http://www.viva64.com/en/a/0073/ 2. Andrey Karpov. Leo Tolstoy and static code analysis. http://www.viva64.com/en/b/0105/ 3. Andrey Karpov. FAQ for those who have read our articles. http://www.viva64.com/en/b/0132/