Analyzing Wine: One Year Later
Author: Svyatoslav Razmyslov
Date: 21.10.2015
One year ago, we picked Wine project to analyze with PVS-Studio and provided the analysis results in an
article within the scope of our practice of analyzing open-source projects. So the article was written and
the project's authors were informed about it. They even asked for a complete analysis log and we
submitted it to them. Recently one of the project developers has contacted us again. In this article I will
tell you about some points of our discussion, several improvements that Wine authors have done in
their code and work that is yet to be done.
Introduction
Wine (Wine Is Not Emulator) is a set of programs allowing Linux, FreeBSD, and Solaris users to run
Windows-applications without installing Microsoft Windows itself. Wine is an actively developing cross-
platform, free and open-source software application distributed under the GNU Lesser General Public
License.
In August 2014, we published an article "Checking Wine with PVS-Studio and Clang Static Analyzer".
Recently we've got an email from one of the Wine developers Michael Stefaniuc, where he thanked PVS-
Studio team for running the analyzer on their code and sharing the analysis report.
He also shared with us some statistics on the bug fixes, suggested by the analyzer. Here you can find 180
commits with source-code fixes labeled "PVS-Studio".
Figure 1 shows statistics on the fixes of 20 diagnostic warnings that the authors find to be most critical
for their project.
Figure 1 - Top 20 successful error codes for Wine
Michael told us that trying to correlate the source code's current version with the old analysis report
had become pretty hard, so he asked us to scan the project once again. Wine is actively developing; so is
the PVS-Studio analyzer. So I decided to give it another run. Results of the new analysis are described in
this small post, where I will tell you about 10 most suspicious code fragments in Wine. We have sent a
complete log to the developers, so they can review all the rest potential issues.
Top 10 warnings
Warning V650
V650 Type casting operation is utilized 2 times in succession. Next, the '+' operation is executed.
Probably meant: (T1)((T2)a + b). descriptor.c 967
WINE_HIDP_PREPARSED_DATA* build_PreparseData(....)
{
....
wine_report =
(WINE_HID_REPORT*)((BYTE*)wine_report)+wine_report->dwSize;
....
}
The analyzer detected an addition operation applied to a variable whose type is being cast twice. The
error probably occurred because the programmer forgot to enclose the first type conversion and
addition operation in parentheses. A bit earlier in the code, there is exactly the same fragment but with
parentheses:
wine_report =
(WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
Warning V590
V590 Consider inspecting the 'lret == 0 || lret != 234' expression. The expression is excessive or contains
a misprint. winemenubuilder.c 3430
static void cleanup_menus(void)
{
...
while (1)
{
....
lret = RegEnumValueW(....);
if (lret == ERROR_SUCCESS || lret != ERROR_MORE_DATA)
break;
....
}
The code contains a redundant comparison "lret == ERROR_SUCCESS". It seems that we are dealing with
a logical error here. The condition is true at any value of the 'lret' variable other than
'ERROR_MORE_DATA'. See the table in Figure 2.
Figure 2 - Truth table for a conditional expression
Marked red are the two columns where the results of logical operations totally coincide.
Another issue of this type:
 V590 Consider inspecting the 'last_error == 183 || last_error != 3' expression. The expression is
excessive or contains a misprint. schedsvc.c 90
Warning V576
V576 Incorrect format. Consider checking the fourth actual argument of the 'printf' function. To print
the value of pointer the '%p' should be used. msvcirt.c 828
DEFINE_THISCALL_WRAPPER(streambuf_dbp, 4)
void __thiscall streambuf_dbp(streambuf *this)
{
....
printf(" base()=%p, ebuf()=%p, blen()=%dn",
this->base, this->ebuf, streambuf_blen(this));
printf("pbase()=%p, pptr()=%p, epptr()=%dn",
this->pbase, this->pptr, this->epptr);
printf("eback()=%p, gptr()=%p, egptr()=%dn",
this->eback, this->gptr, this->egptr);
....
}
The analyzer detected a suspicious code fragment where a pointer's value is attempted to be printed
using the '%d specifier. This code is very likely to have been written by Copy-paste. Supposedly, the first
call of the printf() function was written first and its last argument correctly matches the '%d' specifier.
But then this line was copied twice more and the pointer was passed as the last argument. After all
these actions, the programmer forgot to change the string formatting.
Warning V557
V557 Array overrun is possible. The '16' index is pointing beyond array bound. winaspi32.c 232
/* SCSI Miscellaneous Stuff */
#define SENSE_LEN 14
typedef struct tagSRB32_ExecSCSICmd {
....
BYTE SenseArea[SENSE_LEN+2];
} SRB_ExecSCSICmd, *PSRB_ExecSCSICmd;
static void
ASPI_PrintSenseArea(SRB_ExecSCSICmd *prb)
{
BYTE *rqbuf = prb->SenseArea;
....
if (rqbuf[15]&0x8) {
TRACE("Pointer at %d, bit %dn",
rqbuf[16]*256+rqbuf[17],rqbuf[15]&0x7); //<==
}
....
}
The analyzer detected that the program tries to address items 16 and 17 of the 'rgbuf' array, which is
beyond its bounds as it only contains 16 items. The "rqbuf[15]&0x8" condition is rarely true, that's why
the error hasn't been noticed.
Warning V711
V711 It is dangerous to create a local variable within a loop with a same name as a variable controlling
this loop. dplobby.c 765
static HRESULT WINAPI
IDirectPlayLobby3AImpl_EnumAddressTypes(....)
{
....
FILETIME filetime;
....
/* Traverse all the service providers we have available */
for( dwIndex=0; RegEnumKeyExA( hkResult, dwIndex, subKeyName,
&sizeOfSubKeyName,
NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
++dwIndex, sizeOfSubKeyName=50 )
{
....
FILETIME filetime;
....
/* Traverse all the address type we have available */
for( dwAtIndex=0; RegEnumKeyExA( hkServiceProviderAt,
dwAtIndex, atSubKey, &sizeOfSubKeyName,
NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
++dwAtIndex, sizeOfSubKeyName=50 )
{
....
}
....
}
....
}
The loop body contains declaration of the "filetime" variable, whose name coincides with that of the
variable used to control the loop. This will lead to loss of local changes in "filename" when leaving the
internal loop. The function's entire code suggests that a large code block was copied into the loop body
with just slight edits. Although it may not be necessarily dangerous, it's still not a good style.
Warning V530
V530 The return value of function 'DSCF_AddRef' is required to be utilized. dsound_main.c 760
static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
{
return 2;
}
HRESULT WINAPI DllGetClassObject(....)
{
....
while (NULL != DSOUND_CF[i].rclsid) {
if (IsEqualGUID(rclsid, DSOUND_CF[i].rclsid)) {
DSCF_AddRef(&DSOUND_CF[i].IClassFactory_iface); //<==
*ppv = &DSOUND_CF[i];
return S_OK;
}
i++;
}
....
}
The code contains DSCF_AddRef() function, whose return value is not used. Moreover, this function
doesn't change any program states, which is very suspicious and should be checked by the developers.
Warning V593
V593 Consider reviewing the expression of the 'A = B < C' kind. The expression is calculated as following:
'A = (B < C)'. user.c 3247
DWORD WINAPI FormatMessage16(....)
{
....
int ret;
int sz;
LPSTR b = HeapAlloc(..., sz = 100);
argliststart=args+insertnr-1;
/* CMF - This makes a BIG assumption about va_list */
while ((ret = vsnprintf(....) < 0) || (ret >= sz)) {
sz = (ret == -1 ? sz + 100 : ret + 1);
b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz);
}
....
}
Precedence of logical operations is higher than that of the assignment operation. Therefore, in this
expression, the "vsnprintf(....) < 0" subexpression is evaluated first; consequently, what will be saved
into the 'ret' variable is not the number of characters written, but value 0 or 1 instead. The "ret >= sz"
subexpression will always be false, so the loop will execute only if 'ret' stores 1. And this will be possible
if the vsnprintf() function executes with an error and returns a negative value.
Warning V716
V716 Suspicious type conversion in return statement: returned HRESULT, but function actually returns
BOOL. ordinal.c 5198
#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057)
BOOL WINAPI SHPropertyBag_ReadLONG(....)
{
VARIANT var;
HRESULT hr;
TRACE("%p %s %pn", ppb,debugstr_w(pszPropName),pValue);
if (!pszPropName || !ppb || !pValue)
return E_INVALIDARG;
V_VT(&var) = VT_I4;
hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
if (SUCCEEDED(hr))
{
if (V_VT(&var) == VT_I4)
*pValue = V_I4(&var);
else
hr = DISP_E_BADVARTYPE;
}
return hr;
}
There are plenty of spots in Wine project where the HRESULT type is cast to BOOL or a variable of this
type is handled as a Boolean value. What makes it dangerous is that HRESULT is a fairly complex type
designed to confirm successful operation execution and report the return result or an error's origin, its
conditions, etc., should it occur.
Fortunately, the developers are actively fixing such fragments, and there are lots of corresponding
commits to be found in the bug tracker.
Warning V523
V523 The 'then' statement is equivalent to the 'else' statement. resource.c 661
WORD WINAPI GetDialog32Size16( LPCVOID dialog32 )
{
....
p = (const DWORD *)p + 1; /* x */
p = (const DWORD *)p + 1; /* y */
p = (const DWORD *)p + 1; /* cx */
p = (const DWORD *)p + 1; /* cy */
if (dialogEx)
p = (const DWORD *)p + 1; /* ID */
else
p = (const DWORD *)p + 1; /* ID */
....
}
The analyzer detected a condition with identical branches. Seems that it's just a copy-pasted fragment
that the programmer forgot to edit.
Warning V519
V519 The 'res' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 5905,
5907. action.c 5907
static void test_publish_components(void)
{
....
res = RegCreateKeyExA(....);
res = RegSetValueExA(....);
ok(res == ERROR_SUCCESS, "RegSetValueEx failed %dn", res);
RegCloseKey(key);
....
}
Testing is meant to ensure application's reliability, so it's no good when tests themselves contain errors.
In this code fragment, the programmer forgot to check the result of one function and went on to get
and check the result of another.
Conclusion
In response to the project-rescan request, we've sent the Wine's authors a fresh report of the PVS-
Studio analyzer and a temporary product registration key so that they can comfortably view it through
the PVS-Studio plugin for Visual Studio or Standalone utility. Wine's code has become much cleaner
since the last year, and now the authors will be able to improve it even more.

More Related Content

PDF
Critical errors in CryEngine V code
PDF
Checking 7-Zip with PVS-Studio analyzer
PDF
Top 10 bugs in C++ open source projects, checked in 2016
PDF
Errors detected in the Visual C++ 2012 libraries
PDF
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
PDF
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
PDF
Checking the Cross-Platform Framework Cocos2d-x
PDF
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Critical errors in CryEngine V code
Checking 7-Zip with PVS-Studio analyzer
Top 10 bugs in C++ open source projects, checked in 2016
Errors detected in the Visual C++ 2012 libraries
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...
Checking the Cross-Platform Framework Cocos2d-x
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...

What's hot (20)

PDF
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
PDF
A fresh eye on Oracle VM VirtualBox
PDF
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PPTX
Александр Куцан: "Static Code Analysis in C++"
PDF
systems programming lab programs in c
PDF
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
PDF
Analyzing FreeCAD's Source Code and Its "Sick" Dependencies
PDF
A Spin-off: CryEngine 3 SDK Checked with CppCat
PDF
Picking Mushrooms after Cppcheck
PPTX
What static analyzers can do that programmers and testers cannot
PPTX
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PDF
Reanalyzing the Notepad++ project
PDF
Sony C#/.NET component set analysis
PDF
Checking Clang 11 with PVS-Studio
PDF
Checking OpenCV with PVS-Studio
PDF
PVS-Studio is there to help CERN: analysis of Geant4 project
PDF
Checking WinMerge with PVS-Studio for the second time
PDF
What is new in sulu 2.0
PDF
PVS-Studio team is about to produce a technical breakthrough, but for now let...
PDF
Checking Notepad++: five years later
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
A fresh eye on Oracle VM VirtualBox
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
Александр Куцан: "Static Code Analysis in C++"
systems programming lab programs in c
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
Analyzing FreeCAD's Source Code and Its "Sick" Dependencies
A Spin-off: CryEngine 3 SDK Checked with CppCat
Picking Mushrooms after Cppcheck
What static analyzers can do that programmers and testers cannot
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
Reanalyzing the Notepad++ project
Sony C#/.NET component set analysis
Checking Clang 11 with PVS-Studio
Checking OpenCV with PVS-Studio
PVS-Studio is there to help CERN: analysis of Geant4 project
Checking WinMerge with PVS-Studio for the second time
What is new in sulu 2.0
PVS-Studio team is about to produce a technical breakthrough, but for now let...
Checking Notepad++: five years later
Ad

Viewers also liked (15)

DOCX
Parque sucre
PDF
PROCESSOS FORMATIVOS PARA PROFESSORES PRINCIPIANTES NA EDUCAÇÃO SUPERIOR
PPT
FBI Toolkit Update (Winter 2016)
PPTX
Actividad 6 objetos editables
PDF
Alignez votre marque consommateur et votre marque employeur 160217105725
PDF
Magazine20ans sif
PDF
MCSS16: Under-Appreciated Google Tools
PDF
Estudo ‘Da Prosperidade ao Propósito’, sobre a filantropia entre famílias de ...
PDF
Analyzing source code of WPF examples by the Infragistics Company
PDF
An Ideal Way to Integrate a Static Code Analyzer into a Project
PDF
The tyranny of averages
PPSX
12 MILLAS - OTTO MEDEM ARQUITECT
PDF
RCC_Brochure_2016
PPTX
Passionate Pro v1
Parque sucre
PROCESSOS FORMATIVOS PARA PROFESSORES PRINCIPIANTES NA EDUCAÇÃO SUPERIOR
FBI Toolkit Update (Winter 2016)
Actividad 6 objetos editables
Alignez votre marque consommateur et votre marque employeur 160217105725
Magazine20ans sif
MCSS16: Under-Appreciated Google Tools
Estudo ‘Da Prosperidade ao Propósito’, sobre a filantropia entre famílias de ...
Analyzing source code of WPF examples by the Infragistics Company
An Ideal Way to Integrate a Static Code Analyzer into a Project
The tyranny of averages
12 MILLAS - OTTO MEDEM ARQUITECT
RCC_Brochure_2016
Passionate Pro v1
Ad

Similar to Analyzing Wine: One Year Later (20)

PDF
Checking Wine with PVS-Studio and Clang Static Analyzer
PDF
PVS-Studio delved into the FreeBSD kernel
PDF
How to find 56 potential vulnerabilities in FreeBSD code in one evening
PDF
Linux version of PVS-Studio couldn't help checking CodeLite
PDF
Checking Bitcoin
PDF
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
PDF
Linux Kernel, tested by the Linux-version of PVS-Studio
PDF
Re-checking the ReactOS project - a large report
PDF
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
PPTX
SAST and Application Security: how to fight vulnerabilities in the code
PDF
Checking the code of Valgrind dynamic analyzer by a static analyzer
PDF
Rechecking Apache HTTP Server
PPTX
Static analysis: looking for errors ... and vulnerabilities?
PPTX
PVS-Studio, a solution for resource intensive applications development
PDF
Porting is a Delicate Matter: Checking Far Manager under Linux
PDF
Why Windows 8 drivers are buggy
PDF
Checking Oracle VM VirtualBox. Part 2
PDF
Asterisk: PVS-Studio Takes Up Telephony
PDF
Analyzing ReactOS One More Time
PDF
Can We Trust the Libraries We Use?
Checking Wine with PVS-Studio and Clang Static Analyzer
PVS-Studio delved into the FreeBSD kernel
How to find 56 potential vulnerabilities in FreeBSD code in one evening
Linux version of PVS-Studio couldn't help checking CodeLite
Checking Bitcoin
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Linux Kernel, tested by the Linux-version of PVS-Studio
Re-checking the ReactOS project - a large report
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
SAST and Application Security: how to fight vulnerabilities in the code
Checking the code of Valgrind dynamic analyzer by a static analyzer
Rechecking Apache HTTP Server
Static analysis: looking for errors ... and vulnerabilities?
PVS-Studio, a solution for resource intensive applications development
Porting is a Delicate Matter: Checking Far Manager under Linux
Why Windows 8 drivers are buggy
Checking Oracle VM VirtualBox. Part 2
Asterisk: PVS-Studio Takes Up Telephony
Analyzing ReactOS One More Time
Can We Trust the Libraries We Use?

Recently uploaded (20)

PDF
iTop VPN Crack Latest Version Full Key 2025
PDF
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
PPTX
Computer Software - Technology and Livelihood Education
PDF
Microsoft Office 365 Crack Download Free
PDF
How Tridens DevSecOps Ensures Compliance, Security, and Agility
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PPTX
Matchmaking for JVMs: How to Pick the Perfect GC Partner
PPTX
Tech Workshop Escape Room Tech Workshop
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PPTX
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PPTX
CNN LeNet5 Architecture: Neural Networks
PDF
novaPDF Pro 11.9.482 Crack + License Key [Latest 2025]
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PDF
Guide to Food Delivery App Development.pdf
PDF
MCP Security Tutorial - Beginner to Advanced
PDF
Autodesk AutoCAD Crack Free Download 2025
iTop VPN Crack Latest Version Full Key 2025
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
Computer Software - Technology and Livelihood Education
Microsoft Office 365 Crack Download Free
How Tridens DevSecOps Ensures Compliance, Security, and Agility
DNT Brochure 2025 – ISV Solutions @ D365
Matchmaking for JVMs: How to Pick the Perfect GC Partner
Tech Workshop Escape Room Tech Workshop
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
CNN LeNet5 Architecture: Neural Networks
novaPDF Pro 11.9.482 Crack + License Key [Latest 2025]
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
Guide to Food Delivery App Development.pdf
MCP Security Tutorial - Beginner to Advanced
Autodesk AutoCAD Crack Free Download 2025

Analyzing Wine: One Year Later

  • 1. Analyzing Wine: One Year Later Author: Svyatoslav Razmyslov Date: 21.10.2015 One year ago, we picked Wine project to analyze with PVS-Studio and provided the analysis results in an article within the scope of our practice of analyzing open-source projects. So the article was written and the project's authors were informed about it. They even asked for a complete analysis log and we submitted it to them. Recently one of the project developers has contacted us again. In this article I will tell you about some points of our discussion, several improvements that Wine authors have done in their code and work that is yet to be done. Introduction Wine (Wine Is Not Emulator) is a set of programs allowing Linux, FreeBSD, and Solaris users to run Windows-applications without installing Microsoft Windows itself. Wine is an actively developing cross- platform, free and open-source software application distributed under the GNU Lesser General Public License.
  • 2. In August 2014, we published an article "Checking Wine with PVS-Studio and Clang Static Analyzer". Recently we've got an email from one of the Wine developers Michael Stefaniuc, where he thanked PVS- Studio team for running the analyzer on their code and sharing the analysis report. He also shared with us some statistics on the bug fixes, suggested by the analyzer. Here you can find 180 commits with source-code fixes labeled "PVS-Studio". Figure 1 shows statistics on the fixes of 20 diagnostic warnings that the authors find to be most critical for their project. Figure 1 - Top 20 successful error codes for Wine Michael told us that trying to correlate the source code's current version with the old analysis report had become pretty hard, so he asked us to scan the project once again. Wine is actively developing; so is the PVS-Studio analyzer. So I decided to give it another run. Results of the new analysis are described in this small post, where I will tell you about 10 most suspicious code fragments in Wine. We have sent a complete log to the developers, so they can review all the rest potential issues. Top 10 warnings Warning V650 V650 Type casting operation is utilized 2 times in succession. Next, the '+' operation is executed. Probably meant: (T1)((T2)a + b). descriptor.c 967 WINE_HIDP_PREPARSED_DATA* build_PreparseData(....) { .... wine_report = (WINE_HID_REPORT*)((BYTE*)wine_report)+wine_report->dwSize; .... } The analyzer detected an addition operation applied to a variable whose type is being cast twice. The error probably occurred because the programmer forgot to enclose the first type conversion and
  • 3. addition operation in parentheses. A bit earlier in the code, there is exactly the same fragment but with parentheses: wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize); Warning V590 V590 Consider inspecting the 'lret == 0 || lret != 234' expression. The expression is excessive or contains a misprint. winemenubuilder.c 3430 static void cleanup_menus(void) { ... while (1) { .... lret = RegEnumValueW(....); if (lret == ERROR_SUCCESS || lret != ERROR_MORE_DATA) break; .... } The code contains a redundant comparison "lret == ERROR_SUCCESS". It seems that we are dealing with a logical error here. The condition is true at any value of the 'lret' variable other than 'ERROR_MORE_DATA'. See the table in Figure 2. Figure 2 - Truth table for a conditional expression Marked red are the two columns where the results of logical operations totally coincide. Another issue of this type:  V590 Consider inspecting the 'last_error == 183 || last_error != 3' expression. The expression is excessive or contains a misprint. schedsvc.c 90 Warning V576 V576 Incorrect format. Consider checking the fourth actual argument of the 'printf' function. To print the value of pointer the '%p' should be used. msvcirt.c 828 DEFINE_THISCALL_WRAPPER(streambuf_dbp, 4) void __thiscall streambuf_dbp(streambuf *this) { .... printf(" base()=%p, ebuf()=%p, blen()=%dn", this->base, this->ebuf, streambuf_blen(this)); printf("pbase()=%p, pptr()=%p, epptr()=%dn", this->pbase, this->pptr, this->epptr); printf("eback()=%p, gptr()=%p, egptr()=%dn", this->eback, this->gptr, this->egptr); ....
  • 4. } The analyzer detected a suspicious code fragment where a pointer's value is attempted to be printed using the '%d specifier. This code is very likely to have been written by Copy-paste. Supposedly, the first call of the printf() function was written first and its last argument correctly matches the '%d' specifier. But then this line was copied twice more and the pointer was passed as the last argument. After all these actions, the programmer forgot to change the string formatting. Warning V557 V557 Array overrun is possible. The '16' index is pointing beyond array bound. winaspi32.c 232 /* SCSI Miscellaneous Stuff */ #define SENSE_LEN 14 typedef struct tagSRB32_ExecSCSICmd { .... BYTE SenseArea[SENSE_LEN+2]; } SRB_ExecSCSICmd, *PSRB_ExecSCSICmd; static void ASPI_PrintSenseArea(SRB_ExecSCSICmd *prb) { BYTE *rqbuf = prb->SenseArea; .... if (rqbuf[15]&0x8) { TRACE("Pointer at %d, bit %dn", rqbuf[16]*256+rqbuf[17],rqbuf[15]&0x7); //<== } .... } The analyzer detected that the program tries to address items 16 and 17 of the 'rgbuf' array, which is beyond its bounds as it only contains 16 items. The "rqbuf[15]&0x8" condition is rarely true, that's why the error hasn't been noticed. Warning V711 V711 It is dangerous to create a local variable within a loop with a same name as a variable controlling this loop. dplobby.c 765 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddressTypes(....) { .... FILETIME filetime; .... /* Traverse all the service providers we have available */ for( dwIndex=0; RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; ++dwIndex, sizeOfSubKeyName=50 ) { .... FILETIME filetime; ....
  • 5. /* Traverse all the address type we have available */ for( dwAtIndex=0; RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; ++dwAtIndex, sizeOfSubKeyName=50 ) { .... } .... } .... } The loop body contains declaration of the "filetime" variable, whose name coincides with that of the variable used to control the loop. This will lead to loss of local changes in "filename" when leaving the internal loop. The function's entire code suggests that a large code block was copied into the loop body with just slight edits. Although it may not be necessarily dangerous, it's still not a good style. Warning V530 V530 The return value of function 'DSCF_AddRef' is required to be utilized. dsound_main.c 760 static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface) { return 2; } HRESULT WINAPI DllGetClassObject(....) { .... while (NULL != DSOUND_CF[i].rclsid) { if (IsEqualGUID(rclsid, DSOUND_CF[i].rclsid)) { DSCF_AddRef(&DSOUND_CF[i].IClassFactory_iface); //<== *ppv = &DSOUND_CF[i]; return S_OK; } i++; } .... } The code contains DSCF_AddRef() function, whose return value is not used. Moreover, this function doesn't change any program states, which is very suspicious and should be checked by the developers. Warning V593 V593 Consider reviewing the expression of the 'A = B < C' kind. The expression is calculated as following: 'A = (B < C)'. user.c 3247 DWORD WINAPI FormatMessage16(....) { .... int ret; int sz; LPSTR b = HeapAlloc(..., sz = 100); argliststart=args+insertnr-1;
  • 6. /* CMF - This makes a BIG assumption about va_list */ while ((ret = vsnprintf(....) < 0) || (ret >= sz)) { sz = (ret == -1 ? sz + 100 : ret + 1); b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz); } .... } Precedence of logical operations is higher than that of the assignment operation. Therefore, in this expression, the "vsnprintf(....) < 0" subexpression is evaluated first; consequently, what will be saved into the 'ret' variable is not the number of characters written, but value 0 or 1 instead. The "ret >= sz" subexpression will always be false, so the loop will execute only if 'ret' stores 1. And this will be possible if the vsnprintf() function executes with an error and returns a negative value. Warning V716 V716 Suspicious type conversion in return statement: returned HRESULT, but function actually returns BOOL. ordinal.c 5198 #define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057) BOOL WINAPI SHPropertyBag_ReadLONG(....) { VARIANT var; HRESULT hr; TRACE("%p %s %pn", ppb,debugstr_w(pszPropName),pValue); if (!pszPropName || !ppb || !pValue) return E_INVALIDARG; V_VT(&var) = VT_I4; hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL); if (SUCCEEDED(hr)) { if (V_VT(&var) == VT_I4) *pValue = V_I4(&var); else hr = DISP_E_BADVARTYPE; } return hr; } There are plenty of spots in Wine project where the HRESULT type is cast to BOOL or a variable of this type is handled as a Boolean value. What makes it dangerous is that HRESULT is a fairly complex type designed to confirm successful operation execution and report the return result or an error's origin, its conditions, etc., should it occur. Fortunately, the developers are actively fixing such fragments, and there are lots of corresponding commits to be found in the bug tracker. Warning V523 V523 The 'then' statement is equivalent to the 'else' statement. resource.c 661 WORD WINAPI GetDialog32Size16( LPCVOID dialog32 ) { .... p = (const DWORD *)p + 1; /* x */
  • 7. p = (const DWORD *)p + 1; /* y */ p = (const DWORD *)p + 1; /* cx */ p = (const DWORD *)p + 1; /* cy */ if (dialogEx) p = (const DWORD *)p + 1; /* ID */ else p = (const DWORD *)p + 1; /* ID */ .... } The analyzer detected a condition with identical branches. Seems that it's just a copy-pasted fragment that the programmer forgot to edit. Warning V519 V519 The 'res' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 5905, 5907. action.c 5907 static void test_publish_components(void) { .... res = RegCreateKeyExA(....); res = RegSetValueExA(....); ok(res == ERROR_SUCCESS, "RegSetValueEx failed %dn", res); RegCloseKey(key); .... } Testing is meant to ensure application's reliability, so it's no good when tests themselves contain errors. In this code fragment, the programmer forgot to check the result of one function and went on to get and check the result of another. Conclusion In response to the project-rescan request, we've sent the Wine's authors a fresh report of the PVS- Studio analyzer and a temporary product registration key so that they can comfortably view it through the PVS-Studio plugin for Visual Studio or Standalone utility. Wine's code has become much cleaner since the last year, and now the authors will be able to improve it even more.