SlideShare uma empresa Scribd logo
1 de 46
Baixar para ler offline
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...




          PVS-Studio advertisement - static analysis of
          C/C++ code
          Authors: Andrey Karpov, Evgeniy Ryzhkov

          Date: 25.10.2011

                 Abstract
                 What is static code analysis
                 PVS-Studio tool
                 Types of detectable defects
                 Handling PVS-Studio report
                 Incremental code analysis
                 ROI when using PVS-Studio
                 User support
                 Examples of errors detected in various open-source projects
                       Errors of array and string handling
                       Undefined behavior
                       Errors relating to operation priorities.
                       Formatted output errors
                       Examples of misprints found in code
                       Incorrect use of base functions and classes
                       Examples of meaningless code
                       Always true or always false conditions
                       Code vulnerabilities
                       Copy-Paste
                       Miscellaneous
                 Conclusions
                 References

          Abstract
          This document advertises the PVS-Studio static analyzer. It describes how using PVS-Studio reduces the
          number of errors in code of C/C++/C++11 projects and costs on code testing, debugging and
          maintenance. A lot of examples of errors are cited found by the analyzer in various Open-Source projects.
          The document describes PVS-Studio at the time of version 4.38 on October 12-th, 2011, and therefore
          does not describe the capabilities of the tool in the next versions. To learn about new capabilities, visit the
          product's site http://www.viva64.com or search for an updated version of this article.

          What is static code analysis
          Static code analysis is a methodology of detecting errors in software. It is based on quick and efficient
          review by programmer of code fragments marked by a static analyzer in those places where errors are
          possible. In other words, a static analyzer detects fragments in the program text containing errors, inclined
          to have errors or having bad formatting. These code fragments are reported to the programmer so that
          he/she examines them and decides whether or not a particular program fragment must be modified.

          Static code analysis partly resembles the code review method. The difference between them is that in the


Стр. 1 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          case of static analysis it is software that acts as experts. Of course, software's capabilities are far weaker
          than capabilities of a team of programmers. On the other hand, software cannot get tired, and using it is
          several tens of times cheaper than code review.

          Static analyzers may be both general-purpose (for example, PVS-Studio, Microsoft PREFast, Gimpel
          PC-Lint, Parasoft C++Test) and specialized, i.e. intended for detecting particular sorts of errors (for
          example, Chord intended for verifying parallel Java programs). Static analyzers are usually used in
          companies with a high development culture and mature software development processes. It is determined
          by the fact that static analyzers require understanding of their working principles and spending some time
          on studying and integrating them into a development process. In return they allow you to detect a lot of
          errors at the early stages of program code development.

          The main advantage of using static analyzers is reduction of costs on elimination of defects in a program.
          Thus, according to statistics given in the book "Code Complete" by McConnel, fixing an error at the stage
          of testing is ten times more expensive than at the stage of coding:




          Figure 1. Average cost of fixing defects depending on the time of their appearance and detection (the data
          are taken from the book "Code Complete" by S. McConnel).

          Static analyzers allow you to detect many errors of the coding stage, which makes development of the
          whole project much cheaper.

          PVS-Studio tool
          PVS-Studio is an easy-to-study and easy-to-use static code analyzer. PVS-Studio is an add-on for the
          Visual Studio 2005/2008/2010 development environment. However, the analyzer can be used from the
          command line as well, about which you may learn from the documentation.

          Main characteristics of PVS-Studio:

          Supported languages: C / C++ / C++11 (within the scope of support provided by the Visual C++ compiler
          for these languages).

          Operating systems: 32-bit and 64-bit versions of Windows XP / 2003 / Vista / 2008 / 7.

          System requirements: The analyzer's system requirements coincide with those of Microsoft Visual Studio.

          Operation mode: As an add-on for the Visual Studio 2005/2008/2010 environment. Command line launch


Стр. 2 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          (with solution-file / without solution-file). Note: PVS-Studio cannot work with Visual C++ Express
          Edition since this system does not support add-ons.

          Integration with continuous integration systems: Yes.

          Product's site: http://www.viva64.com/en/

          Documentation: In Russian and English.

          Downloadable demo version: Yes.

          How to purchase: Online.

          Support: prompt support by programmers via e-mail in Russian and English. Support includes
          improvements of the tool allowing you to integrate the product into your project's development process.
          We take account of users' wishes concerning new diagnostic rules.

          Types of detectable defects
          Diagnostic messages of PVS-Studio can be divided into 5 groups:

          1. Diagnostics of concurrency errors in OpenMP programs.

          Despite the fact that the OpenMP technology was actively promoted by Intel company during 2006-2009,
          it failed to attract programmers' interest and is virtually not used now. We decided to leave the
          corresponding diagnostic rules already implemented but stop further development in this direction.
          Consequently, we will not speak of concurrency errors and will switch over to the analyzer's more
          interesting capabilities. Who is interested in the OpenMP topic, visit this section: http://www.viva64.com
          /en/vivamp-tool/ .

          2. Diagnostics of 64-bit errors

          We believe that PVS-Studio has the most powerful set of static analysis rules detecting 64-bit errors.
          These diagnostic rules help to port 32-bit code to a 64-bit platform and control the process of writing new
          64-bit code. We have written a lot of interesting articles about 64-bit errors, you may read them on our
          site:

                 A Collection of Examples of 64-bit Errors in Real Programs: http://www.viva64.com/en/a/0065/
                 A 64-bit horse that can count: http://www.viva64.com/en/a/0043/
                 About size_t and ptrdiff_t: http://www.viva64.com/en/a/0050/
                 "Lessons on development of 64-bit C/C++ applications" course: http://www.viva64.com/en/l/

          In these articles we discuss the topic of 64-bit issues in detail, so we will not dwell upon it here. Let us
          give only one example so that you understand what type of errors we mean:

          dgCollisionCompoundBreakable::dgCollisionCompoundBreakable(...)
          {
            ...
            dgInt32 faceOffsetHitogram[256];
            dgSubMesh* mainSegmenst[256];
            ...
            memset (faceOffsetHitogram, 0, sizeof(faceOffsetHitogram));
            memset (mainSegmenst, 0, sizeof(faceOffsetHitogram));
            ...
          }




Стр. 3 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          This code was detected by PVS-Studio in the Newton Game Dynamics project. Note the second call of
          the 'memset' function. A misprint causes this function to fill with zeroes the 'sizeof(faceOffsetHitogram)'
          byte instead of 'sizeof(mainSegmenst)'.

          Why do we call this error a 64-bit error? The point is that it emerges only when compiling the code in
          64-bit mode. In a 32-bit program, the sizes of pointers and 'dgInt32' type coincide. It means that the size
          of arrays faceOffsetHitogram and mainSegmenst coincide in a 32-bit program. In a 64-bit program these
          arrays have different sizes, that's why the 'memset' function will fill only part of the array.

          3. Detection of ineffective constructs

          PVS-Studio has some rules to detect constructs that can be optimized. Ineffective code is certainly not an
          error, and each programmer should decide himself/herself whether or not he/she needs these diagnostic
          messages. Here is a simple example to clarify this point:

          if ((strlen(directory) > 0) &&
              (directory[strlen(directory)-1] != ''))

          The analyzer will generate the V804 warning for this code. This fragment can be optimized if you
          calculate the string length preliminarily and put it into a temporary variable. It is not necessary in every
          case, but if this code is executed multiple times in a loop, such optimization is really useful.

          4. Diagnostic rules implemented at the request of users

          These rules are rather specific and useful only for a small group of users. They are mentioned for you to
          know that our company is always ready to respond to any wishes of our customers!

          5. General diagnostic rules

          This is the most interesting rule set. It allows you to detect a lot of interesting errors: from misprints to
          potential attack vulnerabilities.

          Examples of source codes are the best advertisement for programmers. So we will not write abstract texts
          about static analysis's capabilities but will show examples of these from practice. If you want to see them
          right now, pass to the section "Examples of errors detected in various open-source projects". Or wait a bit
          and read wholly this modest article praising our tool.

          Handling PVS-Studio report
          If you handle the analyzer in the Visual Studio environment, you will be provided with a simple interface
          consisting of 2 components: a new menu and an interactive window to handle warnings.

          1. PVS-Studio menu




Стр. 4 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code        file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...




          Figure 2. PVS-Studio menu integrated into Visual Studio 2005.

          You can use it to launch analysis, save/load the log, change settings and perform other functions any
          programmer will easily understand.

          2. Integrative window with warnings




          Figure 3. PVS-Studio window to handle warnings (click the screenshot to view in fullscreen mode)

          Functions of the window:

                 Code navigation. Double-click the message, use forward/backward icons or press hot keys 'Alt - ['
                 and 'Alt - ]' to navigate the code.
                 Open a corresponding documentation section for an error you want to know about. Click the error
                 code.
                 Enabling/disabling various warning sets. For example, you may look only through the warnings of
                 the first-level importance relating to 64-bit diagnostics.
                 Various methods of message sorting and filtering. You can search for particular messages. There
                 are also other minor features like "mark with asterisk" those messages you find interesting.
                 For single messages, a pop-up menu is also available (move the pointer to the message and
                 right-click it). For example, you may perform such an important function as marking a diagnostic
                 rule as false (Mark selected errors as False Alarms).


Стр. 5 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...



          Incremental code analysis
          PVS-Studio enables you to cheaply integrate static analysis into a development process.

          If "Incremental Analysis after Build" mode is enabled, the analyzer is launched automatically right after
          compilation and checks only those files that have been "affected" by user editing. That is, the user sees
          errors only in the code he/she is currently writing or affecting during refactoring.

          The programmer does not have to worry about a large size of code he/she does not deal with at the
          moment. This code might be 5 years old; it is not modified, and all the defects in it have been fixed
          already. There is no need in rushing to check this code first of all, and the analyzer does not do it. The
          programmer will see warnings concerning only the fresh code. And when he/she has some spare time,
          he/she may check the whole project looking even into the most rarely visited corners.

          Incremental analysis is performed in background, and you may continue to edit your code without having
          to wait for analysis to get complete. If the analyzer finds something, it will signal to you by changing the
          color of the window icon and a pop-up message.




          Figure 5. PVS-Studio's pop-up message.

          Of course, we all do not like all those annoying pop-ups. But in our case it will be obviously useful for the
          programmer and appear rarely on condition that the programmer does not make too many mistakes in
          code.

          Try it yourself. We are sure that programmers will like this mode.

          ROI when using PVS-Studio
          This section is intended for those cases when you try the PVS-Studio analyzer, and it finds just a few
          errors. You will ask what the benefit of using static analysis is, when it managed to detect only several
          defects. If it happens, remember about this section and read the following 2 posts:

                 Leo Tolstoy and static code analysis: http://www.viva64.com/en/b/0105/
                 Static analysis and ROI: http://www.viva64.com/en/b/0100/

          In brief, the profit of static analysis emerges when you use it regularly and not from time to time. Those
          errors, that PVS-Studio could detect quickly and easily, have been already fixed through such expensive
          procedures as debugging, testing or users feedback.

          User support


Стр. 6 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          It is the analyzer developers themselves who communicate with our customers, which allows them to get
          quick answers even to complex questions relating to programming. We are always ready to help to adapt
          and integrate PVS-Studio into the development process carried out in a customer's company. Here are
          examples of several features we have implemented at the request of our users:

                 creating report files in a particular format;
                 script development for specific modes of PVS-Studio launch;
                 improving the tool to enable it to interact with a particular continuous integration or build system;
                 adding new settings into the tool;
                 choosing only some particular files of a project/solution to check (name filtering or filtering by time
                 when modifications were introduced - for instance, for the last day).

          Besides counseling on using PVS-Studio and aid in integrating static analysis into the everyday
          development process, we take account of users' wishes concerning implementation of new diagnostic
          rules.

          Examples of errors detected in various open-source projects
          We regularly check known and little-known open-source projects. We do it with the purpose to get an
          opportunity to write a corresponding advertisement item and test the PVS-Studio analyzer on new code.
          Many readers ask if we tell projects' authors about errors. Surely. And sometimes it happens that we get a
          new customer after that.

          All the examples of detected errors are divided into several groups. This division is rather relative. One
          and the same error can be referred to misprints, vulnerabilities and incorrect array handling at a time.
          That's why we have arranged the errors in different categories just to show you that the analyzer can
          detect a wide range of various defects.

          We took only a few errors from each of the projects we have checked, of course. If we describe all the
          detected issues, the article will turn into a reference book. Here is a list of projects we have analyzed:

                 Apache HTTP Server - http://httpd.apache.org/
                 Audacity - http://audacity.sourceforge.net/
                 Chromium - http://www.chromium.org/
                 Clang - http://clang-analyzer.llvm.org/
                 CMake - http://www.cmake.org/
                 Crystal Space 3D SDK - http://www.crystalspace3d.org/main/Main_Page
                 Emule - http://www.emule.com/
                 FAR Manager - http://www.farmanager.com/
                 FCE Ultra - http://fceux.com/web/home.html
                 Fennec Media Project - http://fennec.sourceforge.net/
                 G3D Content Pak - http://sourceforge.net/projects/g3d-cpp/
                 IPP Samples - http://www.viva64.com/go.php?url=449
                 Lugaru - http://www.wolfire.com/lugaru
                 Miranda IM - http://www.miranda-im.org/
                 MySQL - http://www.mysql.com/
                 Newton Game Dynamics - http://newtondynamics.com/forum/newton.php
                 Notepad++ - http://notepad-plus-plus.org/
                 Pixie - http://www.renderpixie.com/
                 PNG library - http://libpng.org/pub/png/
                 QT - http://qt.nokia.com/products/



Стр. 7 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code      file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


                 ReactOS - http://www.reactos.org/en/
                 Shareaza - http://www.shareaza.com/
                 SMTP Client with SSL/TLS - http://www.codeproject.com/KB/IP/smtp_ssl.aspx
                 StrongDC++ - http://strongdc.sourceforge.net/index.php?lang=eng
                 Swiss-Army Knife of Trace - http://www.codeproject.com/KB/trace/tracetool.aspx
                 TortoiseSVN - http://tortoisesvn.net/
                 Ultimate TCP/IP - http://www.codeproject.com/KB/MFC/UltimateTCPIP.aspx
                 VirtualDub - http://www.virtualdub.org/
                 WinDjView - http://windjview.sourceforge.net/
                 WinMerge - http://winmerge.org/
                 Wolfenstein 3D - http://en.wikipedia.org/wiki/Wolfenstein_3D
                 And some others.




          Figure 6. Logos of projects we have checked




Стр. 8 из 46                                                                                                      28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...



          Errors of array and string handling

          Errors of array and string handling are the largest class of defects in C/C++ programs. This is the price for
          the capability of effective low-level memory handling available to programmers. In the article we will
          show just a small part of these errors found by the PVS-Studio analyzer. But we think any C/C++
          programmer understands how numerous and insidious they are.

          Example 1. Wolfenstein 3D project. Only part of an object is cleared.

          void CG_RegisterItemVisuals( int itemNum ) {
            ...
            itemInfo_t *itemInfo;
            ...
            memset( itemInfo, 0, sizeof( &itemInfo ) );
            ...
          }

          The error was found through the V568 diagnostic: It's odd that the argument of sizeof() operator is the
          '&itemInfo' expression. cgame cg_weapons.c 1467.

          The sizeof() operator calculates the size of the pointer instead of the 'itemInfo_t' structure's size. It is
          "sizeof(*itemInfo)" that must be written.

          Example 2. Wolfenstein 3D project. Only part of a matrix is cleared.

          ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
            memcpy( mat, src, sizeof( src ) );
          }

          The error was found through the V511: The sizeof() operator returns size of the pointer, and not of the
          array, in 'sizeof(src)' expression. Splines math_matrix.h 94

          Usually programmers expect 'sizeof(src)' to return the size of an array equal to "3*3*sizeof(float)" bytes.
          But according to the language standard, 'src' is just a pointer, not an array. Thus, the matrix will be copied
          only partly. The 'memcpy' function will copy 4 or 8 bytes (the pointer size) depending on whether the
          code is 32-bit or 64-bit.

          If you want the whole matrix to be copied, you may pass a reference to the array into the function. This is
          the correct code:

          ID_INLINE mat3_t::mat3_t( float (&src)[3][3] )
          {
            memcpy( mat, src, sizeof( src ) );
          }

          Example 3. FAR Manager project. Only part of an array is cleared.

          struct TreeItem
          {
            int *Last;
            size_t LastCount;
            ...
            void Clear()
            {
              strName.Clear();
              memset(Last, 0, sizeof(Last));
              Depth=0;
            }
          };



Стр. 9 из 46                                                                                                             28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          The error was found through the V579: diagnostic The memset function receives the pointer and its size
          as arguments. It is probably a mistake. Inspect the third argument. far treelist.hpp 66

          Most likely, there is a missing operation of multiplication by the number of items being cleared, and the
          code must look as follows: "memset(Last, 0, LastCount * sizeof(Last));".

          Example 4. ReactOS project. Incorrect calculation of a string length.

          static const PCHAR Nv11Board = "NV11 (GeForce2) Board";
          static const PCHAR Nv11Chip = "Chip Rev B2";
          static const PCHAR Nv11Vendor = "NVidia Corporation";

          BOOLEAN
          IsVesaBiosOk(...)
          {
            ...
            if (!(strncmp(Vendor, Nv11Vendor, sizeof(Nv11Vendor))) &&
                !(strncmp(Product, Nv11Board, sizeof(Nv11Board))) &&
                !(strncmp(Revision, Nv11Chip, sizeof(Nv11Chip))) &&
                (OemRevision == 0x311))
            ...
          }

          The error was found through the V579 diagnostic: The strncmp function receives the pointer and its size
          as arguments. It is probably a mistake. Inspect the third argument. vga vbe.c 57

          Calls of the 'strncmp' function in this code compare only the first several characters, not whole strings.
          The error here is this: the sizeof() operator, absolutely inappropriate in this situation, is used to calculate
          string lengths. The sizeof() operator actually calculates the pointer size instead of the number of bytes in a
          string.

          What is the most unpleasant and insidious about this error is that this code almost works as intended. In
          99% of cases, comparison of the first several characters is enough. But the remaining 1% can bring you
          much fun and long debugging.

          Example 5. VirtualDub project. Array overrun (explicit index).

          struct ConvoluteFilterData {
           long m[9];
           long bias;
           void *dyna_func;
           DWORD dyna_size;
           DWORD dyna_old_protect;
           BOOL fClip;
          };

          static unsigned long __fastcall do_conv(
            unsigned long *data,
            const ConvoluteFilterData *cfd,
            long sflags, long pit)
          {
            long rt0=cfd->m[9], gt0=cfd->m[9], bt0=cfd->m[9];
            ...
          }

          The error was found through the V557 diagnostic: Array overrun is possible. The '9' index is pointing
          beyond array bound. VirtualDub f_convolute.cpp 73

          This is one of the simplest errors causing an array overrun. Index 9 is used explicitly, though the last
          item's index is 8. The author probably forgot, while writing this code, that array items in C/C++ are


Стр. 10 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          numbered starting with zero, not one. It happens when you have to switch between different programming
          languages.

          Example 6. CPU Identifying Tool project. Array overrun (index in a macro).

          #define FINDBUFFLEN 64 // Max buffer find/replace size
          ...
          int WINAPI Sticky (...)
          {
            ...
            static char findWhat[FINDBUFFLEN] = {'0'};
            ...
            findWhat[FINDBUFFLEN] = '0';
            ...
          }

          The error was found through the V557 diagnostic: Array overrun is possible. The '64' index is pointing
          beyond array bound. stickies stickies.cpp 7947

          This error is a kind of the previous one. The terminal null is written outside the array. The correct code is:
          "findWhat[FINDBUFFLEN - 1] = '0';".

          Example 7. Wolfenstein 3D project. Array overrun (incorrect expression).

          void BotTeamAI( bot_state_t *bs ) {
            ...
            bs->teamleader[sizeof( bs->teamleader )] = '0';
            ...
          }

          The error was found through the V557 diagnostic: Array overrun is possible. The 'sizeof
          (bs->teamleader)' index is pointing beyond array bound. game ai_team.c 548

          Here is one more example of an array overrun when using an explicitly declared index. These samples
          show that such simple at first sight errors are much more widely-spread than it may seem.

          The terminal null is written outside the 'teamleader' array. This is the correct code:
          bs->teamleader[sizeof( bs->teamleader ) - 1] = '0';

          Example 8. Miranda IM project. Only part of a string is copied.

          typedef struct _textrangew
          {
            CHARRANGE chrg;
            LPWSTR lpstrText;
          } TEXTRANGEW;

          const wchar_t* Utils::extractURLFromRichEdit(...)
          {
            ...
            ::CopyMemory(tr.lpstrText, L"mailto:", 7);
            ...
          }

          The error was found through the V512 diagnostic: A call of the 'memcpy' function will lead to a buffer
          overflow or underflow. tabsrmm utils.cpp 1080

          If Unicode-strings are used, one character occupies 2 or 4 bytes (depending on the data model being used
          in compiler) instead of one byte. Unfortunately, programmers easily forget about it, and you can often see


Стр. 11 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          defects like our example in programs.

          The 'CopyMemory' function will copy only part of the L"mailto:" string since it handles bytes, not
          characters. You can fix the code by using a more appropriate function for string copying or, at least,
          multiplying number 7 by sizeof(wchar_t).

          Example 9. CMake project. Array overrun inside a loop.

          static const struct {
            DWORD   winerr;
            int     doserr;
          } doserrors[] =
          {
            ...
          };

          static void
          la_dosmaperr(unsigned long e)
          {
            ...
            for (i = 0; i < sizeof(doserrors); i++)
            {
              if (doserrors[i].winerr == e)
              {
                errno = doserrors[i].doserr;
                return;
              }
            }
            ...
          }

          The error was found through the V557 diagnostic: Array overrun is possible. The value of 'i' index could
          reach 367. cmlibarchive archive_windows.c 1140, 1142

          The error handler itself contains an error. The sizeof() operator returns the array size in bytes and not the
          number of items inside it. As a result, the program will try to search much more items than it should in the
          loop. This is the correct loop:
          for (i = 0; i < sizeof(doserrors) / sizeof(*doserrors); i++)

          Example 10. CPU Identifying Tool project. A string is printed into itself.

          char * OSDetection ()
          {
            ...
            sprintf(szOperatingSystem,
                    "%sversion %d.%d %s (Build %d)",
                    szOperatingSystem,
                    osvi.dwMajorVersion,
                    osvi.dwMinorVersion,
                    osvi.szCSDVersion,
                    osvi.dwBuildNumber & 0xFFFF);
            ...
            sprintf (szOperatingSystem, "%s%s(Build %d)",
                     szOperatingSystem, osvi.szCSDVersion,
                     osvi.dwBuildNumber & 0xFFFF);
            ...
          }

          This error was found through the V541 diagnostic: It is dangerous to print the string 'szOperatingSystem'
          into itself. stickies camel.cpp 572, 603



Стр. 12 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          An attempt of formatted printing of a string into itself can lead to bad consequences. The result of
          executing this code depends on the input data, and you cannot predict what will happen. Most likely, the
          result will be a meaningless string or an Access Violation will occur.

          This error can be referred to the category "code vulnerabilities". In some programs, by feeding special
          data to code, you can exploit such code fragments to cause a buffer overflow or other effects an intruder
          needs.

          Example 11. FCE Ultra project. A string gets less memory than needed.

          int FCEUI_SetCheat(...)
          {
            ...
            if((t=(char *)realloc(next->name,strlen(name+1))))
            ...
          }

          The error was found through the V518 diagnostic: The 'realloc' function allocates strange amount of
          memory calculated by 'strlen(expr)'. Perhaps the correct variant is 'strlen(expr) + 1'. fceux cheat.cpp 609

          This error is caused by a misprint. It is the 'name' pointer instead of the "name+1" expression that must be
          the argument of the strlen() function. As a result, the realloc function allocates 2 bytes less memory than
          needed: one byte is lost because 1 is not added to the string length; another byte is lost because the 'strlen'
          function calculates the string length skipping the first character.

          Example 12. Notepad++ project. Partial array clearing.

          #define CONT_MAP_MAX 50
          int _iContMap[CONT_MAP_MAX];
          ...
          DockingManager::DockingManager()
          {
            ...
            memset(_iContMap, -1, CONT_MAP_MAX);
            ...
          }

          The error was found through the V512 diagnostic: A call of the memset function will lead to a buffer
          overflow or underflow. notepadPlus DockingManager.cpp 60

          That's one more example of how the number of array items is mixed up with an array size. A
          multiplication by sizeof(int) is missing.

          We can go on and on showing you errors of array handling we have found in various programs. But we
          have to stop somewhere. Let it be 12, for number 13 is considered to be unlucky.

          Undefined behavior

          A bit of theory at first.

          Undefined behavior is a property of certain programming languages (most prominent in C and C++) to
          produce a result in certain situations that depends on compiler implementation or specified optimization
          switches. In other words, the specification does not define the language's behavior in any possible
          situations but says: "at A condition, the result of B operation is undefined". It is considered a mistake to
          allow such a situation in your program even if it is executed well at some particular compiler. Such a
          program will not be crossplatform and may cause failures on a different computer, operating system and



Стр. 13 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          even at different compiler's settings.

          A sequence point in programming is any point in a program where it is guaranteed that the side effects of
          all the previous calculations have already emerged while there are no side effects of the following
          calculations yet. To learn more about sequence points and cases of undefined behavior related to sequence
          points, see this post: http://www.viva64.com/en/t/0065/.

          Example 1. Chromium project. Incorrect use of smart pointer.

          void AccessibleContainsAccessible(...)
          {
            ...
            auto_ptr<VARIANT> child_array(new VARIANT[child_count]);
            ...
          }

          The error was found through the V554 diagnostic: Incorrect use of auto_ptr. The memory allocated with
          'new []' will be cleaned using 'delete'. interactive_ui_tests accessibility_win_browsertest.cc 171

          This example demonstrates the case when using a smart pointer can cause undefined behavior. It may be
          expressed through heap damage, program crash, incomplete object destruction or any other failure. The
          error is this: memory is allocated by the new [] operator and released by the delete operator in the
          'auto_ptr' class' destructor:

          ~auto_ptr() {
            delete _Myptr;
          }

          To fix these issues, you should use a more appropriate class, for instance, boost::scoped_array.

          Example 2. IPP Samples project. Classic Undefined behavior.

          template<typename T, Ipp32s size> void HadamardFwdFast(...)
          {
            Ipp32s *pTemp;
            ...
            for(j=0;j<4;j++) {
              a[0] = pTemp[0*4] + pTemp[1*4];
              a[1] = pTemp[0*4] - pTemp[1*4];
              a[2] = pTemp[2*4] + pTemp[3*4];
              a[3] = pTemp[2*4] - pTemp[3*4];
              pTemp = pTemp++;
              ...
            }
            ...
          }

          The error was found through the V567 diagnostic: Undefined behavior. The 'pTemp' variable is modified
          while being used twice between sequence points. me umc_me_cost_func.h 168

          This is a classic example of undefined program behavior. It is this construct which is used to demonstrate
          Undefined behavior in various articles. It is unknown whether 'pTemp' will be incremented by one or not.
          Two actions of changing pTemp variable's value are located in one sequence point. It means that the
          compiler may create the following code:

          pTemp = pTemp + 1;

          pTemp = pTemp;



Стр. 14 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          Or it may create another version of the code:

          TMP = pTemp;

          pTemp = pTemp + 1;

          pTemp = TMP;

          Which of the two code versions will be created depends on the compiler and optimization switches.

          Example 3. Fennec Media Project project. Complex expression.

          uint32 CUnBitArrayOld::DecodeValueRiceUnsigned(uint32 k)
          {
            ...
            while (!(m_pBitArray[m_nCurrentBitIndex >> 5] &
              Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {}
            ...
          }

          The error was found through the V567 diagnostic: Undefined behavior. The 'm_nCurrentBitIndex'
          variable is modified while being used twice at single sequence point. MACLib unbitarrayold.cpp 78

          There are no sequence points between two instances of using the 'm_nCurrentBitIndex' variable. It means
          that the standard does not specify the moment when this variable is incremented. Correspondingly, this
          code may work differently depending on the compiler and optimization switches.

          Example 4. Miranda IM project. Complex expression.

          short ezxml_internal_dtd(ezxml_root_t root,
            char *s, size_t len)
          {
            ...
            while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') {
            ...
          }

          The error was found through the V567 diagnostic: Undefined behavior. The 's' variable is modified while
          being used twice between sequence points.msne zxml.c 371

          Prefix increment of the variable is used here. But it does not mean anything: it cannot be guaranteed that
          the 's' variable will be incremented before calling the strspn() function.

          Errors relating to operation priorities.

          To make understanding of examples easier, let's recall the operation priorities table.




Стр. 15 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code       file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...




          Figure 7 - Operation priorities in C/C++

          Example 1. MySQL project. Priorities of ! and & operations.

          int ha_innobase::create(...)
          {
            ...
            if (srv_file_per_table
                && !mysqld_embedded
                && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
            ...
          }

          The error was found through the V564 diagnostic: The '&' operator is applied to bool type value. You've
          probably forgotten to include parentheses or intended to use the '&&' operator. innobase ha_innodb.cc
          6789


Стр. 16 из 46                                                                                                      28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          The programmer wanted a part of the expression to check that a certain bit in the 'create_info->options'
          variable is equal to zero. But the priority of the '!' operation is higher than that of the '&' operation, that's
          why the expression works by this algorithm:

          ((!create_info->options) & HA_LEX_CREATE_TMP_TABLE)
          We should use additional parentheses if we want the code to work properly:
          (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))

          Or, what we find nicer, write the code in the following way:

          ((create_info->options & HA_LEX_CREATE_TMP_TABLE) == 0)

          Example 2. Emule project. Priorities of * and ++ operations.

          STDMETHODIMP
          CCustomAutoComplete::Next(..., ULONG *pceltFetched)
          {
            ...
            if (pceltFetched != NULL)
              *pceltFetched++;
            ...
          }

          The error was found through the V532 diagnostic: Consider inspecting the statement of '*pointer++'
          pattern. Probably meant: '(*pointer)++'. emule customautocomplete.cpp 277

          If 'pceltFetched' is not a null pointer, the function must increment the variable of the ULONG type this
          pointer refers to. The error is this: the priority of the '++' operation is higher than that of '*' operation
          (pointer dereferencing). The "*pceltFetched++;" line is identical to the following code:

          TMP = pceltFetched + 1;
          *pceltFetched;
          pceltFetched = TMP;

          Virtually it is just increment of the pointer. To make the code correct, we must add parentheses:
          "(*pceltFetched)++;".

          Example 3. Chromium project. Priorities of & and != operations.

          #define FILE_ATTRIBUTE_DIRECTORY 0x00000010

          bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
            ...
            info->is_directory =
              file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0;
            ...
          }

          The error was found through the V564 diagnostic: The '&' operator is applied to bool type value. You've
          probably forgotten to include parentheses or intended to use the '&&' operator. base platform_file_win.cc
          216

          Programmers easily forget that the priority of the '!=' operation is higher than that of '&'. This is what
          happened in our case. As a result, we have the following expression:

          info->is_directory =
            file_info.dwFileAttributes & (0x00000010 != 0);

          Let's simplify the expression:



Стр. 17 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          info->is_directory = file_info.dwFileAttributes & (true);

          Let's simplify it once again:

          info->is_directory = file_info.dwFileAttributes & 1;

          It turns out that we have tested the first bit instead of the fifth bit. To fix this, we need to add parentheses.

          Example 4. BCmenu project. IF and ELSE mixed up.

          void BCMenu::InsertSpaces(void)
          {
            if(IsLunaMenuStyle())
              if(!xp_space_accelerators) return;
            else
              if(!original_space_accelerators) return;
            ...
          }

          The error was found through the V563 diagnostic: It is possible that this 'else' branch must apply to the
          previous 'if' statement. fire bcmenu.cpp 1853

          This is not an error of operation priorities, but one relative to it. The programmer does not take into
          account that the 'else' branch refers to the nearest 'if' operator. We can see that the code justification as if it
          works by the following algorithm:

          if(IsLunaMenuStyle()) {
            if(!xp_space_accelerators) return;
          } else {
            if(!original_space_accelerators) return;
          }

          But actually it is equivalent to the following construct:

          if(IsLunaMenuStyle())
          {
             if(!xp_space_accelerators) {
               return;
             } else {
               if(!original_space_accelerators) return;
             }
          }

          Example 5. IPP Samples project. Priorities of ?: and | operations.

          vm_file* vm_file_fopen(...)
          {
            ...
            mds[3] = FILE_ATTRIBUTE_NORMAL |
                     (islog == 0) ? 0 : FILE_FLAG_NO_BUFFERING;
            ...
          }

          The error was found through the V502 diagnostic: Perhaps the '?:' operator works in a different way than
          it was expected. The '?:' operator has a lower priority than the '|' operator. vm vm_file_win.c 393

          Depending on the 'islog' variable's value, the expression must be either equal to
          "FILE_ATTRIBUTE_NORMAL" or "FILE_ATTRIBUTE_NORMAL |
          FILE_FLAG_NO_BUFFERING". But it does not happen. Priority of the '?:' operation is lower than that
          of '|'. As a result, the code acts as follows:



Стр. 18 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          mds[3] = (FILE_ATTRIBUTE_NORMAL | (islog == 0)) ?
            0 : FILE_FLAG_NO_BUFFERING;

          Let's simplify the expression:

          mds[3] = (0x00000080 | ...) ? 0 : FILE_FLAG_NO_BUFFERING;

          Since FILE_ATTRIBUTE_NORMAL equals 0x00000080, the condition is always true. It means that 0
          will always be written into mds[3].

          Example 6. Newton Game Dynamics project. Priorities of ?: and * operations.

          dgInt32 CalculateConvexShapeIntersection (...)
          {
            ...
            den = dgFloat32 (1.0e-24f) *
                  (den > dgFloat32 (0.0f)) ?
                    dgFloat32 (1.0f) : dgFloat32 (-1.0f);
            ...
          }

          The error was found through the V502 diagnostic: Perhaps the '?:' operator works in a different way than
          it was expected. The '?:' operator has a lower priority than the '*' operator. physics dgminkowskiconv.cpp
          1061

          The error in this code again relates to the low priority of the '?:' operation. The condition for the '?:'
          operator is expressed by a meaningless subexpression "dgFloat32 (1.0e-24f) * (den > dgFloat32 (0.0f))".
          Adding parentheses will solve the issue.

          By the way, programmers often forget how cunning the '?:' operator is. Here is a post on this topic: "How
          to make fewer errors at the stage of code writing. Part N2".

          Formatted output errors

          Examples of these errors are boring and alike, so we will examine only a few samples. The point is that
          functions with a variable number of arguments accept actual arguments incompatible with the format
          string. Any programmer who uses such functions as printf() is familiar with this type of errors.

          Example 1. ReactOS project. Incorrect printing of a WCHAR-character.

          static void REGPROC_unescape_string(WCHAR* str)
          {
            ...
            default:
              fprintf(stderr,
                "Warning! Unrecognized escape sequence: %c'n",
                str[str_idx]);
            ...
          }

          The error was found through the V576 diagnostic: Incorrect format. Consider checking the third actual
          argument of the 'fprintf' function. The char type argument is expected. regedit regproc.c 293

          The fprinf() function must print a character of the char type. But the third argument is a character of the
          WCHAR type. The user will get an incorrectly generated message. To fix the code, we should replace
          '%c' with '%C' in the format string.

          Example 2. Intel AMT SDK project. Character '%' missing.


Стр. 19 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          void addAttribute(...)
          {
            ...
            int index = _snprintf(temp, 1023,
              "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
              "%02x%02x:02x%02x:%02x%02x:%02x%02x",
              value[0],value[1],value[2],value[3],value[4],
              value[5],value[6],value[7],value[8],
              value[9],value[10],value[11],value[12],
              value[13],value[14],value[15]);
            ...
          }

          The error was found through the V576 diagnostic: Incorrect format. A different number of actual
          arguments is expected while calling '_snprintf' function. Expected: 18. Present: 19. mod_pvs
          mod_pvs.cpp 308

          It is not easy to find an error here at first sight. However, the PVS-Studio analyzer does not get tired and
          notices that the function takes more actual arguments than specified in the format string. The reason is
          that the '%' character is missing in one place. Let's single out this fragment:

          "%02x%02x:[HERE]02x%02x:%02x%02x:%02x%02x",

          Example 3. Intel AMT SDK project. Unused argument.

          bool GetUserValues(...)
          {
            ...
            printf("Error: illegal value. Aborting.n", tmp);
            return false;
          }

          The error was found through the V576 diagnostic: Incorrect format. A different number of actual
          arguments is expected while calling 'printf' function. Expected: 1. Present: 2. RemoteControlSample
          remotecontrolsample.cpp 792

          The error is this: the 'tmp' variable is not used in any way when printing the information message.

          Example 4. G3D Content Pak project. Printing of meaningless data.

          class Matrix3 {
            ...
            inline float* operator[] (int iRow) {
            ...
          };
          void AnyVal::serialize(G3D::TextOutput& t) const {
            ...
            const Matrix3& m = *(Matrix3*)m_value;
            ...
            t.printf("%10.5f, %10.5f, %10.5f,n
                     %10.5f, %10.5f, %10.5f,n
                     %10.5f, %10.5f, %10.5f)",
                     m[0, 0], m[0, 1], m[0, 2],
                     m[1, 0], m[1, 1], m[1, 2],
                     m[2, 0], m[2, 1], m[2, 2]);
            ...
          }

          The error was found through the V520 diagnostic: The comma operator ',' in array index expression '[0,
          0]'. graphics3D anyval.cpp 275




Стр. 20 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          The program prints meaningless values instead of the matrix. You may write such a code when you work
          with different programming languages and sometimes forget how to access an item in a two-dimensional
          array in the C language.

          Let's see how the 'm[0, 1]' expression works. At first, expression"0, 1" is calculated. The result of this
          expression is 1. Then the 'operator[]' function is called in the Matrix3 class. The function takes the actual
          argument 1 and returns the pointer to the first string in the matrix. It is the value of this pointer that will
          be printed by the 'printf()' function though it expects a value of the float-type.

          This is the correct code:

          t.printf("%10.5f, %10.5f, %10.5f,n
                   %10.5f, %10.5f, %10.5f,n
                   %10.5f, %10.5f, %10.5f)",
                   m[0][0], m[0][1], m[0][2],
                   m[1][0], m[1][1], m[1][2],
                   m[2][0], m[2][1], m[2][2]);


          Examples of misprints found in code

          A lot of programming errors are caused by misprints. Most of these errors are quickly detected at the early
          stages of testing. But there are some defects of this kind that remain in code for a long time causing
          troubles both to programmers and users.

          You can make these errors much fewer using the PVS-Studio analyzer. It will find them before testing
          starts, which will significantly reduce the cost of defect detection and elimination.

          Example 1. Miranda IM project. Assignment inside IF.

          void CIcqProto::handleUserOffline(BYTE *buf, WORD wLen)
          {
            ...
            else if (wTLVType = 0x29 && wTLVLen == sizeof(DWORD))
            ...
          }

          The error was found through the V560 diagnostic: A part of conditional expression is always true: 0x29.
          icqoscar8 fam_03buddy.cpp 632

          Because of a misprint, there is an assignment taking place inside the condition of the 'if' operator. This is
          the correct condition: "if (wTLVType == 0x29 && wTLVLen == sizeof(DWORD))".

          Example 2. ReactOS project. Assignment error.

          BOOL WINAPI GetMenuItemInfoA(...)
          {
            ...
            mii->cch = mii->cch;
            ...
          }

          The error was found through the V570 diagnostic: The 'mii->cch' variable is assigned to itself. user32
          menu.c 4347

          The value of the variable is assigned to itself. The programmer apparently intended to write it in this way:
          "mii->cch = miiW->cch;".

          Example 3. Clang project. Object name misprinted.


Стр. 21 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          static Value *SimplifyICmpInst(...) {
            ...
            case Instruction::Shl: {
              bool NUW =
                LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap();
              bool NSW =
                LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap();
            ...
          }

          The error was found through the V501 diagnostic: There are identical sub-expressions
          'LBO->hasNoUnsignedWrap ()' to the left and to the right of the '&&' operator. LLVMAnalysis
          instructionsimplify.cpp 1891

          There is a misprint when using variables with similar names. In the first line, both LBO and RBO
          variables must be used. This is the correct code:

          bool NUW = LBO->hasNoUnsignedWrap() && RBO->hasNoUnsignedWrap();

          Example 4. Notepad++ project. Incorrect state test.

          bool _isPointXValid;
          bool _isPointYValid;
          ...
          bool isPointValid() {
            return _isPointXValid && _isPointXValid;
          };

          The error was found through the V501 diagnostic: There are identical sub-expressions to the left and to
          the right of the '&&' operator. _isPointXValid && _isPointXValid

          The name '_isPointXValid' is used twice. The function must actually return this code: "_isPointXValid
          && _isPointYValid".

          Example 5. StrongDC++ project. Unsuccessful check of rn.

          static void getContentLengthAndHeaderLength(...)
          {
            ...
            while(line[linelen] != 'r' && line[linelen] != 'r')
            ...
          }

          The error was found through the V501 diagnostic: There are identical sub-expressions 'line [linelen] !=
          'r'' to the left and to the right of the '&&' operator. miniupnpc miniupnpc.c 153

          Because of a misprint, presence of the 'r' character is checked twice. Actually presence of the 'n'
          character must be checked too.

          Example 6. G3D Content Pak project. A closing parenthesis in a wrong place.

          bool Matrix4::operator==(const Matrix4& other) const {
            if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
              return true;
            }
            ...
          }

          The error was found through the V575 diagnostic: The 'memcmp' function processes '0' elements. Inspect
          the 'third' argument. graphics3D matrix4.cpp 269


Стр. 22 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          One closing parenthesis is in a wrong place. It turns out that the size of the memory area being compared
          is calculated by the "sizeof(Matrix4) == 0" expression. This expression always has the 'false' result. Then
          'false' turns into an integer value equal to 0. This is the correct code:

          if (memcmp(this, &other, sizeof(Matrix4)) == 0) {

          Example 7. QT project. Error of structure member copying.

          PassRefPtr<Structure>
          Structure::getterSetterTransition(Structure* structure)
          {
            ...
            transition->m_propertyStorageCapacity =
              structure->m_propertyStorageCapacity;
            transition->m_hasGetterSetterProperties =
              transition->m_hasGetterSetterProperties;
            transition->m_hasNonEnumerableProperties =
              structure->m_hasNonEnumerableProperties;
            transition->m_specificFunctionThrashCount =
              structure->m_specificFunctionThrashCount;
            ...
          }

          The error was found through the V570 diagnostic: The 'transition->m_hasGetterSetterProperties' variable
          is assigned to itself. QtScript structure.cpp 512

          It is not easy to find an error looking at this code. But it is there. The field 'm_hasGetterSetterProperties' is
          copied into itself. This is the correct code:

          transition->m_hasGetterSetterProperties =
            structure->m_hasGetterSetterProperties;

          Example 8. Apache HTTP Server project. Extra sizeof operator.
          PSECURITY_ATTRIBUTES GetNullACL(void)
          {
            PSECURITY_ATTRIBUTES sa;
            sa = (PSECURITY_ATTRIBUTES)
              LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
            sa->nLength = sizeof(sizeof(SECURITY_ATTRIBUTES));
            ...
          }

          The error was found through the V568 diagnostic: It's odd that the argument of sizeof() operator is the
          'sizeof (SECURITY_ATTRIBUTES)' expression. libhttpd util_win32.c 115

          The field 'nLength' must contain the size of the 'SECURITY_ATTRIBUTES' structure. There is a
          misprint in the code: the 'sizeof' operator is used twice. As a result, the field 'nLength' stores a size of the
          'size_t' type. This is the correct code:

          sa->nLength = sizeof(SECURITY_ATTRIBUTES);

          Example 9. FCE Ultra project. Double variable declaration.

          int iNesSaveAs(char* name)
          {
            ...
            fp = fopen(name,"wb");
            int x = 0;
            if (!fp)
              int x = 1;



Стр. 23 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


              ...
          }

          The error was found through the V561 diagnostic: It's probably better to assign value to 'x' variable than
          to declare it anew. Previous daclaration: ines.cpp, line 960. fceuxines.cpp 962

          The 'x' variable must store information whether or not a file was opened successfully. Because of a
          misprint, a new variable named 'x' is created and initialized instead of assigning 1 to the existing variable.
          This is how the correct code must look:

          if (!fp)
            x = 1;

          Example 10. Notepad++ project. Using && operator instead of &.

          TCHAR GetASCII(WPARAM wParam, LPARAM lParam)
          {
            ...
            result=ToAscii(wParam,
              (lParam >> 16) && 0xff, keys,&dwReturnedValue,0);
            ...
          }

          The error was found through the V560 diagnostic: A part of conditional expression is always true: 0xff.
          notepadPlus babygrid.cpp 694

          The "(lParam >> 16) && 0xff" expression is meaningless and is always equal to 1 (true). A misprint here
          is in using the '&&' operator instead of '&'.

          Example 11. WinDjView project. Incomplete condition.

          inline bool IsValidChar(int c)
          {
            return c == 0x9 || 0xA || c == 0xD || c >= 0x20 &&
                   c <= 0xD7FF || c >= 0xE000 && c <= 0xFFFD ||
                   c >= 0x10000 && c <= 0x10FFFF;
          }

          The error was found through the V560 diagnostic: A part of conditional expression is always true: 0xA.
          WinDjView xmlparser.cpp 45 False

          The IsValidChar function always returns 'true'. Comparison is missing in one place because of a misprint:
          "... || 0xA || ...".

          Example 12. Fennec Media Project project. Extra semicolon.

          int settings_default(void)
          {
            ...
            for(i=0; i<16; i++);
              for(j=0; j<32; j++)
              {
                settings.conversion.equalizer_bands.boost[i][j] = 0.0;
                settings.conversion.equalizer_bands.preamp[i]   = 0.0;
              }
          }

          The error was found through the V529 diagnostic: Odd semicolon ';' after 'for' operator. settings.c 483

          All the C and C++ programmers know how dangerous an extra semicolon ';' is. Unfortunately, this


Стр. 24 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          knowledge does not prevent them from making such misprints. There is an extra semicolon after the first
          'for' operator, which makes this program fragment unable to execute.

          Example 13. QT project. Missing break operator.

          int QCleanlooksStyle::pixelMetric(...)
          {
            ...
            case PM_SpinBoxFrameWidth:
              ret = 3;
              break;
            case PM_MenuBarItemSpacing:
              ret = 6;
            case PM_MenuBarHMargin:
              ret = 0;
              break;
            ...
          }

          The error was found through the V519 diagnostic: The 'ret' variable is assigned values twice successively.
          Perhaps this is a mistake. Check lines: 3765, 3767. QtGui qcleanlooksstyle.cpp 3767

          This is a classic error - 'break' is missing inside the 'switch' operator. I think you do not need any further
          comments here.

          Example 14. Miranda IM project. Assignment instead of comparison.

          int FindItem(...)
          {
            ...
            int ret;
            ret=FindItem(hwnd,dat,hItem,
                         (struct ClcContact ** )&z,
                         (struct ClcGroup ** )&isv,NULL);
            if (ret=0) {return (0);}
            ...
          }

          The error was found through the V559 diagnostic: Suspicious assignment inside the condition expression
          of 'if' operator: ret = 0. clist_mw clcidents.c 179

          There is a misprint inside the condition of the 'if' operator: '=' is written instead of '=='. The function will
          handle the situation incorrectly when a certain item is not found.

          Example 15. IPP Samples project. Incorrect index.

          struct AVS_MB_INFO
          {
            ...
            Ipp8u refIdx[AVS_DIRECTIONS][4];
            ...
          };

          void AVSCompressor::GetRefIndiciesBSlice(void){
            ...
            if (m_pMbInfo->predType[0] & predType)
            {
              m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][0];
              iRefNum += 1;
            }
            if (m_pMbInfo->predType[1] & predType)
            {



Стр. 25 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


                m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][1];
                iRefNum += 1;
              }
              if (m_pMbInfo->predType[2] & predType)
              {
                m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][2];
                iRefNum += 1;
              }
              if (m_pMbInfo->predType[3] & predType)
              {
                m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][30];
                iRefNum += 1;
              }
              ...
          }

          The error was found through the V557 diagnostic: Array overrun is possible. The '30' index is pointing
          beyond array bound. avs_enc umc_avs_enc_compressor_enc_b.cpp 495

          Consider this fragment: "m_pMbInfo->refIdx[dir][30]". Because of a misprint, number 30 is written
          instead of index 3. By the way, this sample shows well how relative our division of errors into categories
          is. This error might well be referred to the category "Errors of array and string handling". The division is
          relative and is made to show diversity of errors the PVS-Studio analyzer can detect.

          Example 16. ReactOS project. Misprint in a macro.

          #define SWAP(a,b,c)          c = a;
                                       a = b;
                                       a = c

          The error was found through the V519 diagnostic: The 'v2' variable is assigned values twice successively.
          Perhaps this is a mistake. Check lines: 343, 343. win32k gradient.c 343

          It is a rather funny misprint in a macro intended to swap values in two variables. Look closely at the code
          and you will see what I mean. This is the correct code:

          #define SWAP(a,b,c)          c = a;
                                       a = b;
                                       b = c

          This time we did not manage to stop at the 13-th example: so many errors in software are caused by
          misprints. There are much more errors of this kind than programmers think. We could go on and on in
          this section but we decide to stop at the 16-th example at last.

          Incorrect use of base functions and classes

          Example 1. Fennec Media Project. Two terminal nulls absent.

          int JoiningProc(HWND hwnd,UINT uMsg,
            WPARAM wParam,LPARAM lParam)
          {
            ...
            OPENFILENAME lofn;
            memset(&lofn, 0, sizeof(lofn));
            ...
            lofn.lpstrFilter = uni("All Files (*.*)0*.*");
            ...
          }

          The error was found through the V540 diagnostic: Member 'lpstrFilter' should point to string terminated


Стр. 26 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          by two 0 characters. base windows.c 5309

          In Windows API there are structures in which pointers to strings must end with two null characters. It is
          that very kind of string the 'lpstrFilter' member in the OPENFILENAME structure points to.

          Description of 'lpstrFilter' in MSDN:

          LPCTSTR

          A buffer containing pairs of null-terminated filter strings. The last string in the buffer must be terminated
          by two NULL characters.

          If you forget to write an additional null at the end, the dialogue of file handling may contain garbage in
          the filter fields. This is the correct code:

          lofn.lpstrFilter = uni("All Files (*.*)0*.*0");

          Example 2. TortoiseSVN project. Incorrect use of 'remove' function.

          STDMETHODIMP CShellExt::Initialize(....)
          {
            ...
            ignoredprops = UTF8ToWide(st.c_str());
            // remove all escape chars ('')
            std::remove(ignoredprops.begin(), ignoredprops.end(), '');
            break;
            ...
          }

          The error was found through the V530 diagnostic: The return value of function 'remove' is required to be
          utilized. contextmenu.cpp 442

          The std::remove function does not remove items from the container. It only shifts the items and returns
          the iterator to the beginning of trash. Assume we have a vector<int> container that contains items
          1,2,3,1,2,3,1,2,3. If we execute the code "remove( v.begin(), v.end(), 2 )", the container will contain items
          1,3,1,3,X,X,X, where X is some trash. The function will return the iterator to the first trash item, so if we
          want to remove these trash items, we need to write the code: "v.erase(remove(v.begin(), v.end(), 2),
          v.end())".

          Example 3. TortoiseSVN project. Using 'empty' function instead of 'clear'.

          CMailMsg& CMailMsg::SetFrom(string sAddress,
                                      string sName)
          {
             if (initIfNeeded())
             {
                // only one sender allowed
                if (m_from.size())
                   m_from.empty();
                m_from.push_back(TStrStrPair(sAddress,sName));
             }
             return *this;
          }

          The error was found through the V530 diagnostic: The return value of function 'empty' is required to be
          utilized. mailmsg.cpp 40

          The error here is this: the vector::empty() function is called by mistake instead of vector::clear(), and the
          array's contents remain the same. It is a very frequent error because the words 'clear' and 'empty' are rather


Стр. 27 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          close in meaning, and you might easily mix them up.

          Example 4. WinMerge project. Using 'empty' function instead of 'clear'.

          void CDirView::GetItemFileNames(int sel,
            String& strLeft, String& strRight) const
          {
            UINT_PTR diffpos = GetItemKey(sel);
            if (diffpos == (UINT_PTR)SPECIAL_ITEM_POS)
            {
              strLeft.empty();
              strRight.empty();
            }
            else
            {
               ...
            }
          }

          The error was found through the V530 diagnostic: The return value of function 'empty' is required to be
          utilized WinMerge DirActions.cpp 1307, 1308

          Again, the reason is in using the empty() function instead of clear(). We could cite examples of such
          errors from other projects as well: InstantVNC, IPP Samples, Chromium, Intel AMT SDK, etc.
          Unfortunately, all these samples are alike, and there is nothing interesting about examining them. But
          trust me, you can see these defects in serious projects developed by professional programmers.

          Example 5. Pixie project. Using 'alloca' function inside loops.

          inline void triangulatePolygon(...) {
            ...
            for (i=1;i<nloops;i++) {
              ...
              do {
                ...
                do {
                   ...
                   CTriVertex *snVertex =
                    (CTriVertex *)alloca(2*sizeof(CTriVertex));
                   ...
                } while(dVertex != loops[0]);
                ...
              } while(sVertex != loops[i]);
              ...
            }
            ...
          }

          The error was found through the V505 diagnostic: The 'alloca' function is used inside the loop. This can
          quickly overflow stack. ri polygons.cpp 1120

          The alloca function allocates memory inside the stack, so calling it many times inside the loop body may
          suddenly cause a stack overflow. And we have several nested loops here. This code may exhaust stack
          memory very quickly.

          Example 6. Miranda IM project. Arguments mixed up.

          static BOOL ImageArray_Alloc(LP_IMAGE_ARRAY_DATA iad, int size)
          {
            ...
            memset(&iad->nodes[iad->nodes_allocated_size],



Стр. 28 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code          file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


                (size_grow - iad->nodes_allocated_size) *
                    sizeof(IMAGE_ARRAY_DATA_NODE),
                0);
              ...
          }

          The error was found through the V575 diagnostic: Function receives an odd argument. clist_modern
          modern_image_array.cpp 59

          The 'memset' function handles 0 items, i.e. actually does nothing. The reason is in mixed up arguments.
          This is how the correct call of the memset function should be written:

          memset(&iad->nodes[iad->nodes_allocated_size],
            0,
            (size_grow - iad->nodes_allocated_size) *
               sizeof(IMAGE_ARRAY_DATA_NODE));


          Examples of meaningless code

          Example 1. IPP Samples project. Incomplete condition.

          void lNormalizeVector_32f_P3IM(Ipp32f *vec[3],
            Ipp32s* mask, Ipp32s len)
          {
            Ipp32s i;
            Ipp32f norm;

              for(i=0; i<len; i++) {
                if(mask<0) continue;
                norm = 1.0f/sqrt(vec[0][i]*vec[0][i]+
                         vec[1][i]*vec[1][i]+vec[2][i]*vec[2][i]);
                vec[0][i] *= norm; vec[1][i] *= norm; vec[2][i] *= norm;
              }
          }

          The error was found through the V503 diagnostic: This is a nonsensical comparison: pointer < 0.
          ipprsample ippr_sample.cpp 501

          I do not know how it happened, but there are 3 characters "[i]" missing in this code. As a result, the code
          performs a meaningless check that the pointer is below zero instead of checking the mask array.

          The correct check should be written in this way: if(mask[i] < 0).

          Example 2. Pc Ps2 Emulator project. Incorrect switch.

          LRESULT CALLBACK IOP_DISASM(...)
          {
            ...
            switch(LOWORD(wParam))
            {
              case (IDOK || IDCANCEL):
                EndDialog(hDlg,TRUE);
                return(TRUE);
                break;
            }
            ...
          }

          The error was found through the V560 diagnostic: A part of conditional expression is always true: 2.
          pcsx2 debugger.cpp 321



Стр. 29 из 46                                                                                                         28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          This code does not have any meaning. The programmer must have intended to write it this way:

          switch(LOWORD(wParam))
          {
            case IDOK: //no break
            case IDCANCEL:
              EndDialog(hDlg,TRUE);
              return(TRUE);
              break;
          }

          Example 3. CPU Identifying Tool project. A too strict condition.

          void projillum(short* wtab, int xdots, int ydots, double dec)
          {
            ...
            s = sin(-dtr(dec));
            x = -s * sin(th);
            y = cos(th);
            ...
            lon = (y == 0 && x == 0) ? 0.0 : rtd(atan2(y, x));
          }

          The error was found through the V550 diagnostic: An odd precise comparison: x == 0. It's probably better
          to use a comparison with defined precision: fabs(A - B) '<' Epsilon. clock_dll sunalgo.cpp 155

          It is strange to expect that the result will be strictly 0 after executing all these complex calculations using
          'sin' and 'cos' functions. Most likely, there must be comparison to be performed with certain accuracy.

          Example 4. Lugaru. Double assignment.

          int Game::DrawGLScene(void)
          {
            ...
            radius=fast_sqrt(maxdistance);
            radius=110;
            ...
          }

          The error was found through the V519 diagnostic: The 'radius' object is assigned values twice
          successively. Perhaps this is a mistake. Lugaru gamedraw.cpp 1505

          The programmer must have deliberately written value 110 into the 'radius' variable for the sake of
          experiment and then forgot to remove this line. As a result, we have a meaningless and maybe even
          invalid code.

          Example 5. QT project. Duplicated check.

          Q3TextCustomItem* Q3TextDocument::parseTable(...)
          {
            ...
            while (end < length
              && !hasPrefix(doc, length, end, QLatin1String("</td"))
              && !hasPrefix(doc, length, end, QLatin1String("<td"))
              && !hasPrefix(doc, length, end, QLatin1String("</th"))
              && !hasPrefix(doc, length, end, QLatin1String("<th"))
              && !hasPrefix(doc, length, end, QLatin1String("<td"))
              && !hasPrefix(doc, length, end, QLatin1String("</tr"))
              && !hasPrefix(doc, length, end, QLatin1String("<tr"))
              && !hasPrefix(doc, length, end, QLatin1String("</table"))) {

            ...



Стр. 30 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          }

          The error was found through the V501 diagnostic: There are identical sub-expressions to the left and to
          the right of the '&&' operator. Qt3Support q3richtext.cpp 6978

          Presence of the "<td" prefix is checked twice in the condition. It is meaningless. Maybe it is an extra
          check or there should be some other prefix instead of the second "<td".

          Example 6. Audacity project. Strange check.

          int sf_error (SNDFILE *sndfile)
          {
            ...
            if (!sndfile)
            {
              if (sf_error != 0)
                return sf_errno;
              return 0;
            } ;
            ...
          }

          The error was found through the V516 diagnostic: Consider inspecting an odd expression. Non-null
          function pointer is compared to null: 'sf_error != 0'. libsndfile sndfile.c 491

          The "sf_error != 0" check always returns true, since 'sf_error' is the name of the function in which the
          code is executed.

          Example 7. IPP Samples project. Strange code inside a loop.

          static IppStatus mp2_HuffmanTableInitAlloc(Ipp32s *tbl, ...)
          {
            ...
            for (i = 0; i < num_tbl; i++) {
              *tbl++;
            }
            ...
          }

          The error was found through the V532 diagnostic: Consider inspecting the statement of '*pointer++'
          pattern. Probably meant: '(*pointer)++'. mpeg2_dec umc_mpeg2_dec.cpp 59

          The loop body is probably incomplete because it is meaningless in the current form.

          Always true or always false conditions

          It is a very large and widely-spread type of errors. These errors also vary greatly depending on the
          importance level. To non-dangerous errors we may refer incorrect conditions in ASSERT that actually do
          not check anything. To dangerous errors, incorrect checks of buffer size or index size are referred.

          Example 1. Shareaza project. Value range of char type.

          void CRemote::Output(LPCTSTR pszName)
          {

              ...
              CHAR* pBytes = new CHAR[ nBytes ];
              hFile.Read( pBytes, nBytes );
              ...
              if ( nBytes > 3 && pBytes[0] == 0xEF &&



Стр. 31 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


                      pBytes[1] == 0xBB && pBytes[2] == 0xBF )
              {
                  pBytes += 3;
                  nBytes -= 3;
                  bBOM = true;
              }
              ...
          }

          The error was found through the V547 diagnostic: Expression 'pBytes [ 0 ] == 0xEF' is always false. The
          value range of signed char type: [-128, 127]. Shareaza remote.cpp 350

          In this code, the 'TCHAR' type is the 'char' type. The value range of char is from -128 to 127 inclusive.
          Value 0xEF in the variable of the char type is nothing else than number -17. When comparing the char
          variable with number 0xEF, its type is extended up to the 'int' type. But the value still lies inside the range
          [-128..127]. The "pBytes[0] == 0xEF" ("-17 == 0xEF") condition is always false, and the program does
          not work as intended.

          This is the correct comparison:

          if ( nBytes > 3 && pBytes[0] == TCHAR(0xEF) &&
                             pBytes[1] == TCHAR(0xBB) &&
                             pBytes[2] == TCHAR(0xBF) )

          Example 2. TortoiseSVN project. Value range of char type.

          BOOL TortoiseBlame::OpenFile(const TCHAR *fileName)
          {
            ...
            // check each line for illegal utf8 sequences.
            // If one is found, we treat
            // the file as ASCII, otherwise we assume
            // an UTF8 file.
            char * utf8CheckBuf = lineptr;
            while ((bUTF8)&&(*utf8CheckBuf))
            {
              if ((*utf8CheckBuf == 0xC0)||
                  (*utf8CheckBuf == 0xC1)||
                  (*utf8CheckBuf >= 0xF5))
              {
                bUTF8 = false;
                break;
              }

                ...
              }
              ...
          }

          The error was found through the V547 diagnostic: Expression '* utf8CheckBuf == 0xC0' is always false.
          The value range of signed char type: [-128, 127]. tortoiseblame.cpp 310

          While the defect in the previous example seems to be caused through mere inattention, in this case it is
          not so. Here is another identical example where a condition is always false. This is a very widely-spread
          type of errors in various projects.

          Example 3. VirtualDub project. Unsigned type is always >= 0.

          typedef unsigned short wint_t;
          ...
          void lexungetc(wint_t c) {



Стр. 32 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


              if (c < 0)
                return;
               g_backstack.push_back(c);
          }

          The error was found through the V547 diagnostic: Expression 'c < 0' is always false. Unsigned type value
          is never < 0. Ami lexer.cpp 225

          The "c < 0" condition is always false because the variable of the unsigned type is always above or equal
          to 0.

          Example 4. Swiss-Army Knife of Trace project. Socket handling.

          static UINT_PTR m_socketHandle;

          void TTrace::LoopMessages(void)
          {
            ...
            // Socket creation
            if ( (m_socketHandle = socket(AF_INET,SOCK_STREAM,0)) < 0)
            {
              continue;
            }
            ...
          }

          The error was found through the V547 diagnostic: Expression '(m_socketHandle = socket (2, 1, 0)) < 0' is
          always false. Unsigned type value is never < 0. Vs8_Win_Lib tracetool.cpp 871

          An attempt to check that a socket was created successfully is performed incorrectly. If a socket cannot be
          created, this situation is not handled in any way. To make the check work correctly, we should use the
          INVALID_SOCKET constant:

          m_socketHandle = socket(AF_INET,SOCK_STREAM,0);
          if (m_socketHandle == INVALID_SOCKET)

          Example 5. Chromium project. Time handling.
          IdleState CalculateIdleState(...) {
            ...
            DWORD current_idle_time = 0;
            ...
            // Will go -ve if we have been idle for
            // a long time (2gb seconds).
            if (current_idle_time < 0)
              current_idle_time = INT_MAX;
            ...
          }

          The error was found through the V547 diagnostic: Expression 'current_idle_time < 0' is always false.
          Unsigned type value is never < 0. browser idle_win.cc 23

          To handle time, a variable of the unsigned type is used. As a result, check of too large values does not
          work. This is the correct code:

          if (current_idle_time > INT_MAX)
            current_idle_time = INT_MAX;

          Example 6. ICU project. Error in condition.

          U_CDECL_BEGIN static const char* U_CALLCONV



Стр. 33 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          _processVariableTop(...)
          {
            ...
            if(i == locElementCapacity &&
                (*string != 0 || *string != '_'))
            {
              *status = U_BUFFER_OVERFLOW_ERROR;
            }
            ...
          }

          The error was found through the V547 diagnostic: Expression '*string != 0 || *string != '_'' is always true.
          Probably the '&&' operator should be used here. icui18n ucol_sit.cpp 242

          The condition contains a logical error. The "(*string != 0 || *string != '_')" subexpression is always true. It
          is impossible that one and the same string character is not equal to 0 and '_' at a time.

          Example 7. QT project. Dangerous loop.

          bool equals( class1* val1, class2* val2 ) const{
          {
            ...
            size_t size = val1->size();
            ...
            while ( --size >= 0 ){
              if ( !comp(*itr1,*itr2) )
                return false;
              itr1++;
              itr2++;
            }
            ...
          }

          The error was found through the V547 diagnostic: Expression '--size >= 0' is always true. Unsigned type
          value is always >= 0. QtCLucene arrays.h 154

          The (--size >= 0) condition is always true, since the size variable has the unsigned type. It means that if
          two sequences being compared are alike, we will get an overflow that will in its turn cause Access
          Violation or other program failures.

          This is the correct code:

          for (size_t i = 0; i != size; i++){
            if ( !comp(*itr1,*itr2) )
              return false;
            itr1++;
            itr2++;
          }

          Example 8. MySQL project. Error in condition.

          enum enum_mysql_timestamp_type
          str_to_datetime(...)
          {
            ...
            else if (str[0] != 'a' || str[0] != 'A')
              continue; /* Not AM/PM */
            ...
          }

          The error was found through the V547 diagnostic: Expression 'str [0] != 'a' || str [0] != 'A'' is always true.
          Probably the '&&' operator should be used here. clientlib my_time.c 340


Стр. 34 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code           file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          The condition is always true because the character is always either not equal to 'a' or to 'A'. This is the
          correct check:

          else if (str[0] != 'a' && str[0] != 'A')

          Example 9. QT project. Incorrect count of references.

          STDMETHODIMP QEnumPins::QueryInterface(const IID &iid,void **out)
          {
            ...
            if (S_OK)
              AddRef();
            return hr;
          }

          The error was found through the V545 diagnostic: Such conditional expression of 'if' operator is incorrect
          for the HRESULT type value '(HRESULT) 0L'. The SUCCEEDED or FAILED macro should be used
          instead. phonon_ds9 qbasefilter.cpp 60

          The check condition is represented by the S_OK constant. Since S_OK is 0, the AddRef() function will
          never be called. This is how this check must look: if (hr == S_OK).

          Example 10. TickerTape project. Incorrect tornado.

          void GetWindAtSingleTornado(...)
          {
            ...
            if(radius < THRESH * 5)
                *yOut = THRESH * 10 / radius;
            else if (radius < THRESH * 5)
                *yOut = -3.0f / (THRESH * 5.0f) *
                       (radius - THRESH * 5.0f) + 3.0f;
            else
                *yOut = 0.0f;
            ...
          }

          The error was found through the V517 diagnostic: The use of 'if (A) {...} else if (A) {...}' pattern was
          detected. There is a probability of logical error presence. TickerTape wind.cpp 118

          The second condition is always false. The reason is that the first condition coincides with the second.
          There must be a misprint here.

          Example 11. Apache HTTP Server project. Error of socket handling in Windows.

          typedef UINT_PTR SOCKET;

          static unsigned int __stdcall win9x_accept(void * dummy)
          {
            SOCKET csd;
            ...
            do {
                clen = sizeof(sa_client);
                csd = accept(nsd, (struct sockaddr *) &sa_client, &clen);
            } while (csd < 0 && APR_STATUS_IS_EINTR(apr_get_netos_error()));
            ...
          }

          The error was found through the V547 diagnostic: Expression 'csd < 0' is always false. Unsigned type
          value is never < 0. libhttpd child.c 404



Стр. 35 из 46                                                                                                          28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code         file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          Socket handling errors very often emerge in crossplatform programs built under Windows. In Linux,
          socket descriptors are represented by the signed type, while in Windows it is the unsigned type.
          Programmers often forget about this and check the error status by comparing the value to 0. This is
          incorrect; you must use specialized constants.

          Example 12. QT project. Misprint in comparisons.

          QStringList ProFileEvaluator::Private::values(...)
          {
            ...
            else if (ver == QSysInfo::WV_NT)
              ret = QLatin1String("WinNT");
            else if (ver == QSysInfo::WV_2000)
              ret = QLatin1String("Win2000");
            else if (ver == QSysInfo::WV_2000) <<--
              ret = QLatin1String("Win2003");
            else if (ver == QSysInfo::WV_XP)
              ret = QLatin1String("WinXP");
            ...
          }

          The error was found through the V517 diagnostic: The use of 'if (A) {...} else if (A) {...}' pattern was
          detected. There is a probability of logical error presence. Check lines: 2303, 2305. lrelease
          profileevaluator.cpp 2303

          In the string we have marked, there must be the text "ver == QSysInfo::WV_2003". Because of this error,
          the "ret = QLatin1String("Win2003")" statement will never be executed.

          Code vulnerabilities

          Of course, errors leading to code vulnerabilities are actually misprints, incorrect conditions and incorrect
          array handling. But we decided to single out certain errors into a separate group because they relate to the
          notion of software vulnerabilities. An intruder, using such errors, can try to disturb program operation,
          perform an attack to gain extended rights or carry out any other actions he/she needs.

          Example 1. Ultimate TCP/IP project. Incorrect check of an empty string.

          char *CUT_CramMd5::GetClientResponse(LPCSTR ServerChallenge)
          {
            ...
            if (m_szPassword != NULL)
            {
              ...
              if (m_szPassword != '0')
              {
            ...
          }

          The error was found through the V528 diagnostic: It is odd that pointer to 'char' type is compared with the
          '0' value. Probably meant: *m_szPassword != '0'. UTMail ut_crammd5.cpp 333

          This code fragment must check that the pointer to the password is not equal to NULL and that the string is
          not empty. But instead, the code checks twice that the pointer is not equal to NULL. The check of the
          string does not work. The "if (m_szPassword != '0')" condition was intended to check that there is a
          terminal null in the very beginning of the string, which means that the string is empty. But a pointer
          dereferencing operation is missing here, and it is the pointer itself which is compared to zero. This is the
          correct code:



Стр. 36 из 46                                                                                                        28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code            file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana...


          if (m_szPassword != NULL)
          {
            ...
            if (*m_szPassword != '0')

          Example 2. Chromium project. Null pointer handling.

          bool ChromeFrameNPAPI::Invoke(...)
          {
            ChromeFrameNPAPI* plugin_instance =
              ChromeFrameInstanceFromNPObject(header);
            if (!plugin_instance &&
                (plugin_instance->automation_client_.get()))
              return false;
            ...
          }

          The error was found through the V522 diagnostic: Dereferencing of the null pointer 'plugin_instance'
          might take place. Check the logical condition. chrome_frame_npapi chrome_frame_npapi.cc 517

          The condition that checks the null pointer is written incorrectly. As a result, we have a segmentation error.
          This is the correct code:

          if (plugin_instance &&
              (plugin_instance->automation_client_.get()))
            return false;

          Example 3. SMTP Client with SSL/TLS project. Incomplete buffer clearing.

          void MD5::finalize () {
            ...
            uint1 buffer[64];
            ...
            // Zeroize sensitive information
            memset (buffer, 0, sizeof(*buffer));
            ...
          }

          The error was found through the V512 diagnostic: A call of the 'memset' function will lead to a buffer
          overflow or underflow. CSmtp md5.cpp 212

          For security purposes, the function tries to clear the buffer containing sensitive information. But it fails.
          Only the first byte will be cleared in the buffer. The error is this: the 'sizeof' operator calculates the size of
          the 'uint1' type instead of buffer. This is the correct code:

          memset (buffer, 0, sizeof(buffer));

          Generally, errors of incomplete memory clearing are rather frequent. Consider some other cases like this.

          Example 4. Chromium. Incomplete buffer clearing.

          void Time::Explode(..., Exploded* exploded) const {
            ...
            ZeroMemory(exploded, sizeof(exploded));
            ...
          }

          The error was found through the V512 diagnostic: A call of the 'memset' function will lead to underflow
          of the buffer '(exploded)'. base time_win.cc 227

          The ZeroMemory function clears only part of the Exploded structure. The reason is that the 'sizeof'


Стр. 37 из 46                                                                                                           28.10.2011 14:05
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code

Mais conteúdo relacionado

Mais procurados

The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That CouldPVS-Studio
 
Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Andrey Karpov
 
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-StudioHow to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-StudioPVS-Studio
 
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 EngineAndrey Karpov
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in DoxygenPVS-Studio
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsAndrey Karpov
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedAndrey Karpov
 
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...PVS-Studio
 
Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016PVS-Studio
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggyPVS-Studio
 
PVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating systemPVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating systemAndrey Karpov
 
PVS-Studio and static code analysis technique
PVS-Studio and static code analysis techniquePVS-Studio and static code analysis technique
PVS-Studio and static code analysis techniqueAndrey Karpov
 
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 AnalyzerAndrey Karpov
 
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 correctionPVS-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 CodeLitePVS-Studio
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioPVS-Studio
 
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자Taeyeop Kim
 
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 VirtualBoxPVS-Studio
 
Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?PVS-Studio
 
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...Andrey Karpov
 

Mais procurados (20)

The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6
 
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-StudioHow to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
 
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
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in Doxygen
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not used
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
PVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating systemPVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating system
 
PVS-Studio and static code analysis technique
PVS-Studio and static code analysis techniquePVS-Studio and static code analysis technique
PVS-Studio and static code analysis technique
 
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
 
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
 
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
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자
IoT 개발자를 위한 Embedded C에서 Test Coverage를 추출해보자
 
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
 
Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?Of complicacy of programming, or won't C# save us?
Of complicacy of programming, or won't C# save us?
 
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...
 

Semelhante a PVS-Studio advertisement - static analysis of C/C++ code

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++ codePVS-Studio
 
What's the Difference Between Static Analysis and Compiler Warnings?
What's the Difference Between Static Analysis and Compiler Warnings?What's the Difference Between Static Analysis and Compiler Warnings?
What's the Difference Between Static Analysis and Compiler Warnings?Andrey Karpov
 
Information sheet PVS-Studio
Information sheet PVS-StudioInformation sheet PVS-Studio
Information sheet PVS-StudioPVS-Studio
 
Comparing Functionalities of PVS-Studio and CppCat Static Code Analyzers
Comparing Functionalities of PVS-Studio and CppCat Static Code AnalyzersComparing Functionalities of PVS-Studio and CppCat Static Code Analyzers
Comparing Functionalities of PVS-Studio and CppCat Static Code AnalyzersAndrey Karpov
 
Traps detection during migration of C and C++ code to 64-bit Windows
Traps detection during migration of C and C++ code to 64-bit WindowsTraps detection during migration of C and C++ code to 64-bit Windows
Traps detection during migration of C and C++ code to 64-bit WindowsPVS-Studio
 
New Year PVS-Studio 6.00 Release: Scanning Roslyn
New Year PVS-Studio 6.00 Release: Scanning RoslynNew Year PVS-Studio 6.00 Release: Scanning Roslyn
New Year PVS-Studio 6.00 Release: Scanning RoslynPVS-Studio
 
How we test the code analyzer
How we test the code analyzerHow we test the code analyzer
How we test the code analyzerPVS-Studio
 
Static Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to IntegrationStatic Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to IntegrationAndrey Karpov
 
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 developmentPVS-Studio
 
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 developmentPVS-Studio
 
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 developmentAndrey Karpov
 
Static analysis as part of the development process in Unreal Engine
Static analysis as part of the development process in Unreal EngineStatic analysis as part of the development process in Unreal Engine
Static analysis as part of the development process in Unreal EnginePVS-Studio
 
PVS-Studio confesses its love for Linux
PVS-Studio confesses its love for LinuxPVS-Studio confesses its love for Linux
PVS-Studio confesses its love for LinuxPVS-Studio
 
How we test the code analyzer
How we test the code analyzerHow we test the code analyzer
How we test the code analyzerPVS-Studio
 
Control source code quality using the SonarQube platform
Control source code quality using the SonarQube platformControl source code quality using the SonarQube platform
Control source code quality using the SonarQube platformPVS-Studio
 
Problems of testing 64-bit applications
Problems of testing 64-bit applicationsProblems of testing 64-bit applications
Problems of testing 64-bit applicationsPVS-Studio
 
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-StudioPVS-Studio
 
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...PVS-Studio
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2Akhil Mittal
 
PVS-Studio Has Finally Got to Boost
PVS-Studio Has Finally Got to BoostPVS-Studio Has Finally Got to Boost
PVS-Studio Has Finally Got to BoostAndrey Karpov
 

Semelhante a PVS-Studio advertisement - static analysis of C/C++ code (20)

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
 
What's the Difference Between Static Analysis and Compiler Warnings?
What's the Difference Between Static Analysis and Compiler Warnings?What's the Difference Between Static Analysis and Compiler Warnings?
What's the Difference Between Static Analysis and Compiler Warnings?
 
Information sheet PVS-Studio
Information sheet PVS-StudioInformation sheet PVS-Studio
Information sheet PVS-Studio
 
Comparing Functionalities of PVS-Studio and CppCat Static Code Analyzers
Comparing Functionalities of PVS-Studio and CppCat Static Code AnalyzersComparing Functionalities of PVS-Studio and CppCat Static Code Analyzers
Comparing Functionalities of PVS-Studio and CppCat Static Code Analyzers
 
Traps detection during migration of C and C++ code to 64-bit Windows
Traps detection during migration of C and C++ code to 64-bit WindowsTraps detection during migration of C and C++ code to 64-bit Windows
Traps detection during migration of C and C++ code to 64-bit Windows
 
New Year PVS-Studio 6.00 Release: Scanning Roslyn
New Year PVS-Studio 6.00 Release: Scanning RoslynNew Year PVS-Studio 6.00 Release: Scanning Roslyn
New Year PVS-Studio 6.00 Release: Scanning Roslyn
 
How we test the code analyzer
How we test the code analyzerHow we test the code analyzer
How we test the code analyzer
 
Static Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to IntegrationStatic Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to Integration
 
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
 
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
 
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
 
Static analysis as part of the development process in Unreal Engine
Static analysis as part of the development process in Unreal EngineStatic analysis as part of the development process in Unreal Engine
Static analysis as part of the development process in Unreal Engine
 
PVS-Studio confesses its love for Linux
PVS-Studio confesses its love for LinuxPVS-Studio confesses its love for Linux
PVS-Studio confesses its love for Linux
 
How we test the code analyzer
How we test the code analyzerHow we test the code analyzer
How we test the code analyzer
 
Control source code quality using the SonarQube platform
Control source code quality using the SonarQube platformControl source code quality using the SonarQube platform
Control source code quality using the SonarQube platform
 
Problems of testing 64-bit applications
Problems of testing 64-bit applicationsProblems of testing 64-bit applications
Problems of testing 64-bit applications
 
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
 
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...
Using PVS-Studio analyzer together with Microsoft Visual Studio 2010 incremen...
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2
 
PVS-Studio Has Finally Got to Boost
PVS-Studio Has Finally Got to BoostPVS-Studio Has Finally Got to Boost
PVS-Studio Has Finally Got to Boost
 

Mais de Andrey Karpov

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программистаAndrey Karpov
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developerAndrey Karpov
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Andrey Karpov
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesAndrey Karpov
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewAndrey Karpov
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокAndrey Karpov
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Andrey Karpov
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesAndrey Karpov
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?Andrey Karpov
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaAndrey Karpov
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)Andrey Karpov
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Andrey Karpov
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerAndrey Karpov
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareAndrey Karpov
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++Andrey Karpov
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?Andrey Karpov
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youAndrey Karpov
 
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOpsPVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOpsAndrey Karpov
 
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...Andrey Karpov
 

Mais de Andrey Karpov (20)

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

Último

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
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 DevelopmentsTrustArc
 
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?Igalia
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
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.pdfsudhanshuwaghmare1
 

Último (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
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
 
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?
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
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
 

PVS-Studio advertisement - static analysis of C/C++ code

  • 1. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... PVS-Studio advertisement - static analysis of C/C++ code Authors: Andrey Karpov, Evgeniy Ryzhkov Date: 25.10.2011 Abstract What is static code analysis PVS-Studio tool Types of detectable defects Handling PVS-Studio report Incremental code analysis ROI when using PVS-Studio User support Examples of errors detected in various open-source projects Errors of array and string handling Undefined behavior Errors relating to operation priorities. Formatted output errors Examples of misprints found in code Incorrect use of base functions and classes Examples of meaningless code Always true or always false conditions Code vulnerabilities Copy-Paste Miscellaneous Conclusions References Abstract This document advertises the PVS-Studio static analyzer. It describes how using PVS-Studio reduces the number of errors in code of C/C++/C++11 projects and costs on code testing, debugging and maintenance. A lot of examples of errors are cited found by the analyzer in various Open-Source projects. The document describes PVS-Studio at the time of version 4.38 on October 12-th, 2011, and therefore does not describe the capabilities of the tool in the next versions. To learn about new capabilities, visit the product's site http://www.viva64.com or search for an updated version of this article. What is static code analysis Static code analysis is a methodology of detecting errors in software. It is based on quick and efficient review by programmer of code fragments marked by a static analyzer in those places where errors are possible. In other words, a static analyzer detects fragments in the program text containing errors, inclined to have errors or having bad formatting. These code fragments are reported to the programmer so that he/she examines them and decides whether or not a particular program fragment must be modified. Static code analysis partly resembles the code review method. The difference between them is that in the Стр. 1 из 46 28.10.2011 14:05
  • 2. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... case of static analysis it is software that acts as experts. Of course, software's capabilities are far weaker than capabilities of a team of programmers. On the other hand, software cannot get tired, and using it is several tens of times cheaper than code review. Static analyzers may be both general-purpose (for example, PVS-Studio, Microsoft PREFast, Gimpel PC-Lint, Parasoft C++Test) and specialized, i.e. intended for detecting particular sorts of errors (for example, Chord intended for verifying parallel Java programs). Static analyzers are usually used in companies with a high development culture and mature software development processes. It is determined by the fact that static analyzers require understanding of their working principles and spending some time on studying and integrating them into a development process. In return they allow you to detect a lot of errors at the early stages of program code development. The main advantage of using static analyzers is reduction of costs on elimination of defects in a program. Thus, according to statistics given in the book "Code Complete" by McConnel, fixing an error at the stage of testing is ten times more expensive than at the stage of coding: Figure 1. Average cost of fixing defects depending on the time of their appearance and detection (the data are taken from the book "Code Complete" by S. McConnel). Static analyzers allow you to detect many errors of the coding stage, which makes development of the whole project much cheaper. PVS-Studio tool PVS-Studio is an easy-to-study and easy-to-use static code analyzer. PVS-Studio is an add-on for the Visual Studio 2005/2008/2010 development environment. However, the analyzer can be used from the command line as well, about which you may learn from the documentation. Main characteristics of PVS-Studio: Supported languages: C / C++ / C++11 (within the scope of support provided by the Visual C++ compiler for these languages). Operating systems: 32-bit and 64-bit versions of Windows XP / 2003 / Vista / 2008 / 7. System requirements: The analyzer's system requirements coincide with those of Microsoft Visual Studio. Operation mode: As an add-on for the Visual Studio 2005/2008/2010 environment. Command line launch Стр. 2 из 46 28.10.2011 14:05
  • 3. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... (with solution-file / without solution-file). Note: PVS-Studio cannot work with Visual C++ Express Edition since this system does not support add-ons. Integration with continuous integration systems: Yes. Product's site: http://www.viva64.com/en/ Documentation: In Russian and English. Downloadable demo version: Yes. How to purchase: Online. Support: prompt support by programmers via e-mail in Russian and English. Support includes improvements of the tool allowing you to integrate the product into your project's development process. We take account of users' wishes concerning new diagnostic rules. Types of detectable defects Diagnostic messages of PVS-Studio can be divided into 5 groups: 1. Diagnostics of concurrency errors in OpenMP programs. Despite the fact that the OpenMP technology was actively promoted by Intel company during 2006-2009, it failed to attract programmers' interest and is virtually not used now. We decided to leave the corresponding diagnostic rules already implemented but stop further development in this direction. Consequently, we will not speak of concurrency errors and will switch over to the analyzer's more interesting capabilities. Who is interested in the OpenMP topic, visit this section: http://www.viva64.com /en/vivamp-tool/ . 2. Diagnostics of 64-bit errors We believe that PVS-Studio has the most powerful set of static analysis rules detecting 64-bit errors. These diagnostic rules help to port 32-bit code to a 64-bit platform and control the process of writing new 64-bit code. We have written a lot of interesting articles about 64-bit errors, you may read them on our site: A Collection of Examples of 64-bit Errors in Real Programs: http://www.viva64.com/en/a/0065/ A 64-bit horse that can count: http://www.viva64.com/en/a/0043/ About size_t and ptrdiff_t: http://www.viva64.com/en/a/0050/ "Lessons on development of 64-bit C/C++ applications" course: http://www.viva64.com/en/l/ In these articles we discuss the topic of 64-bit issues in detail, so we will not dwell upon it here. Let us give only one example so that you understand what type of errors we mean: dgCollisionCompoundBreakable::dgCollisionCompoundBreakable(...) { ... dgInt32 faceOffsetHitogram[256]; dgSubMesh* mainSegmenst[256]; ... memset (faceOffsetHitogram, 0, sizeof(faceOffsetHitogram)); memset (mainSegmenst, 0, sizeof(faceOffsetHitogram)); ... } Стр. 3 из 46 28.10.2011 14:05
  • 4. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... This code was detected by PVS-Studio in the Newton Game Dynamics project. Note the second call of the 'memset' function. A misprint causes this function to fill with zeroes the 'sizeof(faceOffsetHitogram)' byte instead of 'sizeof(mainSegmenst)'. Why do we call this error a 64-bit error? The point is that it emerges only when compiling the code in 64-bit mode. In a 32-bit program, the sizes of pointers and 'dgInt32' type coincide. It means that the size of arrays faceOffsetHitogram and mainSegmenst coincide in a 32-bit program. In a 64-bit program these arrays have different sizes, that's why the 'memset' function will fill only part of the array. 3. Detection of ineffective constructs PVS-Studio has some rules to detect constructs that can be optimized. Ineffective code is certainly not an error, and each programmer should decide himself/herself whether or not he/she needs these diagnostic messages. Here is a simple example to clarify this point: if ((strlen(directory) > 0) && (directory[strlen(directory)-1] != '')) The analyzer will generate the V804 warning for this code. This fragment can be optimized if you calculate the string length preliminarily and put it into a temporary variable. It is not necessary in every case, but if this code is executed multiple times in a loop, such optimization is really useful. 4. Diagnostic rules implemented at the request of users These rules are rather specific and useful only for a small group of users. They are mentioned for you to know that our company is always ready to respond to any wishes of our customers! 5. General diagnostic rules This is the most interesting rule set. It allows you to detect a lot of interesting errors: from misprints to potential attack vulnerabilities. Examples of source codes are the best advertisement for programmers. So we will not write abstract texts about static analysis's capabilities but will show examples of these from practice. If you want to see them right now, pass to the section "Examples of errors detected in various open-source projects". Or wait a bit and read wholly this modest article praising our tool. Handling PVS-Studio report If you handle the analyzer in the Visual Studio environment, you will be provided with a simple interface consisting of 2 components: a new menu and an interactive window to handle warnings. 1. PVS-Studio menu Стр. 4 из 46 28.10.2011 14:05
  • 5. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Figure 2. PVS-Studio menu integrated into Visual Studio 2005. You can use it to launch analysis, save/load the log, change settings and perform other functions any programmer will easily understand. 2. Integrative window with warnings Figure 3. PVS-Studio window to handle warnings (click the screenshot to view in fullscreen mode) Functions of the window: Code navigation. Double-click the message, use forward/backward icons or press hot keys 'Alt - [' and 'Alt - ]' to navigate the code. Open a corresponding documentation section for an error you want to know about. Click the error code. Enabling/disabling various warning sets. For example, you may look only through the warnings of the first-level importance relating to 64-bit diagnostics. Various methods of message sorting and filtering. You can search for particular messages. There are also other minor features like "mark with asterisk" those messages you find interesting. For single messages, a pop-up menu is also available (move the pointer to the message and right-click it). For example, you may perform such an important function as marking a diagnostic rule as false (Mark selected errors as False Alarms). Стр. 5 из 46 28.10.2011 14:05
  • 6. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Incremental code analysis PVS-Studio enables you to cheaply integrate static analysis into a development process. If "Incremental Analysis after Build" mode is enabled, the analyzer is launched automatically right after compilation and checks only those files that have been "affected" by user editing. That is, the user sees errors only in the code he/she is currently writing or affecting during refactoring. The programmer does not have to worry about a large size of code he/she does not deal with at the moment. This code might be 5 years old; it is not modified, and all the defects in it have been fixed already. There is no need in rushing to check this code first of all, and the analyzer does not do it. The programmer will see warnings concerning only the fresh code. And when he/she has some spare time, he/she may check the whole project looking even into the most rarely visited corners. Incremental analysis is performed in background, and you may continue to edit your code without having to wait for analysis to get complete. If the analyzer finds something, it will signal to you by changing the color of the window icon and a pop-up message. Figure 5. PVS-Studio's pop-up message. Of course, we all do not like all those annoying pop-ups. But in our case it will be obviously useful for the programmer and appear rarely on condition that the programmer does not make too many mistakes in code. Try it yourself. We are sure that programmers will like this mode. ROI when using PVS-Studio This section is intended for those cases when you try the PVS-Studio analyzer, and it finds just a few errors. You will ask what the benefit of using static analysis is, when it managed to detect only several defects. If it happens, remember about this section and read the following 2 posts: Leo Tolstoy and static code analysis: http://www.viva64.com/en/b/0105/ Static analysis and ROI: http://www.viva64.com/en/b/0100/ In brief, the profit of static analysis emerges when you use it regularly and not from time to time. Those errors, that PVS-Studio could detect quickly and easily, have been already fixed through such expensive procedures as debugging, testing or users feedback. User support Стр. 6 из 46 28.10.2011 14:05
  • 7. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... It is the analyzer developers themselves who communicate with our customers, which allows them to get quick answers even to complex questions relating to programming. We are always ready to help to adapt and integrate PVS-Studio into the development process carried out in a customer's company. Here are examples of several features we have implemented at the request of our users: creating report files in a particular format; script development for specific modes of PVS-Studio launch; improving the tool to enable it to interact with a particular continuous integration or build system; adding new settings into the tool; choosing only some particular files of a project/solution to check (name filtering or filtering by time when modifications were introduced - for instance, for the last day). Besides counseling on using PVS-Studio and aid in integrating static analysis into the everyday development process, we take account of users' wishes concerning implementation of new diagnostic rules. Examples of errors detected in various open-source projects We regularly check known and little-known open-source projects. We do it with the purpose to get an opportunity to write a corresponding advertisement item and test the PVS-Studio analyzer on new code. Many readers ask if we tell projects' authors about errors. Surely. And sometimes it happens that we get a new customer after that. All the examples of detected errors are divided into several groups. This division is rather relative. One and the same error can be referred to misprints, vulnerabilities and incorrect array handling at a time. That's why we have arranged the errors in different categories just to show you that the analyzer can detect a wide range of various defects. We took only a few errors from each of the projects we have checked, of course. If we describe all the detected issues, the article will turn into a reference book. Here is a list of projects we have analyzed: Apache HTTP Server - http://httpd.apache.org/ Audacity - http://audacity.sourceforge.net/ Chromium - http://www.chromium.org/ Clang - http://clang-analyzer.llvm.org/ CMake - http://www.cmake.org/ Crystal Space 3D SDK - http://www.crystalspace3d.org/main/Main_Page Emule - http://www.emule.com/ FAR Manager - http://www.farmanager.com/ FCE Ultra - http://fceux.com/web/home.html Fennec Media Project - http://fennec.sourceforge.net/ G3D Content Pak - http://sourceforge.net/projects/g3d-cpp/ IPP Samples - http://www.viva64.com/go.php?url=449 Lugaru - http://www.wolfire.com/lugaru Miranda IM - http://www.miranda-im.org/ MySQL - http://www.mysql.com/ Newton Game Dynamics - http://newtondynamics.com/forum/newton.php Notepad++ - http://notepad-plus-plus.org/ Pixie - http://www.renderpixie.com/ PNG library - http://libpng.org/pub/png/ QT - http://qt.nokia.com/products/ Стр. 7 из 46 28.10.2011 14:05
  • 8. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... ReactOS - http://www.reactos.org/en/ Shareaza - http://www.shareaza.com/ SMTP Client with SSL/TLS - http://www.codeproject.com/KB/IP/smtp_ssl.aspx StrongDC++ - http://strongdc.sourceforge.net/index.php?lang=eng Swiss-Army Knife of Trace - http://www.codeproject.com/KB/trace/tracetool.aspx TortoiseSVN - http://tortoisesvn.net/ Ultimate TCP/IP - http://www.codeproject.com/KB/MFC/UltimateTCPIP.aspx VirtualDub - http://www.virtualdub.org/ WinDjView - http://windjview.sourceforge.net/ WinMerge - http://winmerge.org/ Wolfenstein 3D - http://en.wikipedia.org/wiki/Wolfenstein_3D And some others. Figure 6. Logos of projects we have checked Стр. 8 из 46 28.10.2011 14:05
  • 9. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Errors of array and string handling Errors of array and string handling are the largest class of defects in C/C++ programs. This is the price for the capability of effective low-level memory handling available to programmers. In the article we will show just a small part of these errors found by the PVS-Studio analyzer. But we think any C/C++ programmer understands how numerous and insidious they are. Example 1. Wolfenstein 3D project. Only part of an object is cleared. void CG_RegisterItemVisuals( int itemNum ) { ... itemInfo_t *itemInfo; ... memset( itemInfo, 0, sizeof( &itemInfo ) ); ... } The error was found through the V568 diagnostic: It's odd that the argument of sizeof() operator is the '&itemInfo' expression. cgame cg_weapons.c 1467. The sizeof() operator calculates the size of the pointer instead of the 'itemInfo_t' structure's size. It is "sizeof(*itemInfo)" that must be written. Example 2. Wolfenstein 3D project. Only part of a matrix is cleared. ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) { memcpy( mat, src, sizeof( src ) ); } The error was found through the V511: The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof(src)' expression. Splines math_matrix.h 94 Usually programmers expect 'sizeof(src)' to return the size of an array equal to "3*3*sizeof(float)" bytes. But according to the language standard, 'src' is just a pointer, not an array. Thus, the matrix will be copied only partly. The 'memcpy' function will copy 4 or 8 bytes (the pointer size) depending on whether the code is 32-bit or 64-bit. If you want the whole matrix to be copied, you may pass a reference to the array into the function. This is the correct code: ID_INLINE mat3_t::mat3_t( float (&src)[3][3] ) { memcpy( mat, src, sizeof( src ) ); } Example 3. FAR Manager project. Only part of an array is cleared. struct TreeItem { int *Last; size_t LastCount; ... void Clear() { strName.Clear(); memset(Last, 0, sizeof(Last)); Depth=0; } }; Стр. 9 из 46 28.10.2011 14:05
  • 10. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... The error was found through the V579: diagnostic The memset function receives the pointer and its size as arguments. It is probably a mistake. Inspect the third argument. far treelist.hpp 66 Most likely, there is a missing operation of multiplication by the number of items being cleared, and the code must look as follows: "memset(Last, 0, LastCount * sizeof(Last));". Example 4. ReactOS project. Incorrect calculation of a string length. static const PCHAR Nv11Board = "NV11 (GeForce2) Board"; static const PCHAR Nv11Chip = "Chip Rev B2"; static const PCHAR Nv11Vendor = "NVidia Corporation"; BOOLEAN IsVesaBiosOk(...) { ... if (!(strncmp(Vendor, Nv11Vendor, sizeof(Nv11Vendor))) && !(strncmp(Product, Nv11Board, sizeof(Nv11Board))) && !(strncmp(Revision, Nv11Chip, sizeof(Nv11Chip))) && (OemRevision == 0x311)) ... } The error was found through the V579 diagnostic: The strncmp function receives the pointer and its size as arguments. It is probably a mistake. Inspect the third argument. vga vbe.c 57 Calls of the 'strncmp' function in this code compare only the first several characters, not whole strings. The error here is this: the sizeof() operator, absolutely inappropriate in this situation, is used to calculate string lengths. The sizeof() operator actually calculates the pointer size instead of the number of bytes in a string. What is the most unpleasant and insidious about this error is that this code almost works as intended. In 99% of cases, comparison of the first several characters is enough. But the remaining 1% can bring you much fun and long debugging. Example 5. VirtualDub project. Array overrun (explicit index). struct ConvoluteFilterData { long m[9]; long bias; void *dyna_func; DWORD dyna_size; DWORD dyna_old_protect; BOOL fClip; }; static unsigned long __fastcall do_conv( unsigned long *data, const ConvoluteFilterData *cfd, long sflags, long pit) { long rt0=cfd->m[9], gt0=cfd->m[9], bt0=cfd->m[9]; ... } The error was found through the V557 diagnostic: Array overrun is possible. The '9' index is pointing beyond array bound. VirtualDub f_convolute.cpp 73 This is one of the simplest errors causing an array overrun. Index 9 is used explicitly, though the last item's index is 8. The author probably forgot, while writing this code, that array items in C/C++ are Стр. 10 из 46 28.10.2011 14:05
  • 11. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... numbered starting with zero, not one. It happens when you have to switch between different programming languages. Example 6. CPU Identifying Tool project. Array overrun (index in a macro). #define FINDBUFFLEN 64 // Max buffer find/replace size ... int WINAPI Sticky (...) { ... static char findWhat[FINDBUFFLEN] = {'0'}; ... findWhat[FINDBUFFLEN] = '0'; ... } The error was found through the V557 diagnostic: Array overrun is possible. The '64' index is pointing beyond array bound. stickies stickies.cpp 7947 This error is a kind of the previous one. The terminal null is written outside the array. The correct code is: "findWhat[FINDBUFFLEN - 1] = '0';". Example 7. Wolfenstein 3D project. Array overrun (incorrect expression). void BotTeamAI( bot_state_t *bs ) { ... bs->teamleader[sizeof( bs->teamleader )] = '0'; ... } The error was found through the V557 diagnostic: Array overrun is possible. The 'sizeof (bs->teamleader)' index is pointing beyond array bound. game ai_team.c 548 Here is one more example of an array overrun when using an explicitly declared index. These samples show that such simple at first sight errors are much more widely-spread than it may seem. The terminal null is written outside the 'teamleader' array. This is the correct code: bs->teamleader[sizeof( bs->teamleader ) - 1] = '0'; Example 8. Miranda IM project. Only part of a string is copied. typedef struct _textrangew { CHARRANGE chrg; LPWSTR lpstrText; } TEXTRANGEW; const wchar_t* Utils::extractURLFromRichEdit(...) { ... ::CopyMemory(tr.lpstrText, L"mailto:", 7); ... } The error was found through the V512 diagnostic: A call of the 'memcpy' function will lead to a buffer overflow or underflow. tabsrmm utils.cpp 1080 If Unicode-strings are used, one character occupies 2 or 4 bytes (depending on the data model being used in compiler) instead of one byte. Unfortunately, programmers easily forget about it, and you can often see Стр. 11 из 46 28.10.2011 14:05
  • 12. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... defects like our example in programs. The 'CopyMemory' function will copy only part of the L"mailto:" string since it handles bytes, not characters. You can fix the code by using a more appropriate function for string copying or, at least, multiplying number 7 by sizeof(wchar_t). Example 9. CMake project. Array overrun inside a loop. static const struct { DWORD winerr; int doserr; } doserrors[] = { ... }; static void la_dosmaperr(unsigned long e) { ... for (i = 0; i < sizeof(doserrors); i++) { if (doserrors[i].winerr == e) { errno = doserrors[i].doserr; return; } } ... } The error was found through the V557 diagnostic: Array overrun is possible. The value of 'i' index could reach 367. cmlibarchive archive_windows.c 1140, 1142 The error handler itself contains an error. The sizeof() operator returns the array size in bytes and not the number of items inside it. As a result, the program will try to search much more items than it should in the loop. This is the correct loop: for (i = 0; i < sizeof(doserrors) / sizeof(*doserrors); i++) Example 10. CPU Identifying Tool project. A string is printed into itself. char * OSDetection () { ... sprintf(szOperatingSystem, "%sversion %d.%d %s (Build %d)", szOperatingSystem, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); ... sprintf (szOperatingSystem, "%s%s(Build %d)", szOperatingSystem, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); ... } This error was found through the V541 diagnostic: It is dangerous to print the string 'szOperatingSystem' into itself. stickies camel.cpp 572, 603 Стр. 12 из 46 28.10.2011 14:05
  • 13. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... An attempt of formatted printing of a string into itself can lead to bad consequences. The result of executing this code depends on the input data, and you cannot predict what will happen. Most likely, the result will be a meaningless string or an Access Violation will occur. This error can be referred to the category "code vulnerabilities". In some programs, by feeding special data to code, you can exploit such code fragments to cause a buffer overflow or other effects an intruder needs. Example 11. FCE Ultra project. A string gets less memory than needed. int FCEUI_SetCheat(...) { ... if((t=(char *)realloc(next->name,strlen(name+1)))) ... } The error was found through the V518 diagnostic: The 'realloc' function allocates strange amount of memory calculated by 'strlen(expr)'. Perhaps the correct variant is 'strlen(expr) + 1'. fceux cheat.cpp 609 This error is caused by a misprint. It is the 'name' pointer instead of the "name+1" expression that must be the argument of the strlen() function. As a result, the realloc function allocates 2 bytes less memory than needed: one byte is lost because 1 is not added to the string length; another byte is lost because the 'strlen' function calculates the string length skipping the first character. Example 12. Notepad++ project. Partial array clearing. #define CONT_MAP_MAX 50 int _iContMap[CONT_MAP_MAX]; ... DockingManager::DockingManager() { ... memset(_iContMap, -1, CONT_MAP_MAX); ... } The error was found through the V512 diagnostic: A call of the memset function will lead to a buffer overflow or underflow. notepadPlus DockingManager.cpp 60 That's one more example of how the number of array items is mixed up with an array size. A multiplication by sizeof(int) is missing. We can go on and on showing you errors of array handling we have found in various programs. But we have to stop somewhere. Let it be 12, for number 13 is considered to be unlucky. Undefined behavior A bit of theory at first. Undefined behavior is a property of certain programming languages (most prominent in C and C++) to produce a result in certain situations that depends on compiler implementation or specified optimization switches. In other words, the specification does not define the language's behavior in any possible situations but says: "at A condition, the result of B operation is undefined". It is considered a mistake to allow such a situation in your program even if it is executed well at some particular compiler. Such a program will not be crossplatform and may cause failures on a different computer, operating system and Стр. 13 из 46 28.10.2011 14:05
  • 14. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... even at different compiler's settings. A sequence point in programming is any point in a program where it is guaranteed that the side effects of all the previous calculations have already emerged while there are no side effects of the following calculations yet. To learn more about sequence points and cases of undefined behavior related to sequence points, see this post: http://www.viva64.com/en/t/0065/. Example 1. Chromium project. Incorrect use of smart pointer. void AccessibleContainsAccessible(...) { ... auto_ptr<VARIANT> child_array(new VARIANT[child_count]); ... } The error was found through the V554 diagnostic: Incorrect use of auto_ptr. The memory allocated with 'new []' will be cleaned using 'delete'. interactive_ui_tests accessibility_win_browsertest.cc 171 This example demonstrates the case when using a smart pointer can cause undefined behavior. It may be expressed through heap damage, program crash, incomplete object destruction or any other failure. The error is this: memory is allocated by the new [] operator and released by the delete operator in the 'auto_ptr' class' destructor: ~auto_ptr() { delete _Myptr; } To fix these issues, you should use a more appropriate class, for instance, boost::scoped_array. Example 2. IPP Samples project. Classic Undefined behavior. template<typename T, Ipp32s size> void HadamardFwdFast(...) { Ipp32s *pTemp; ... for(j=0;j<4;j++) { a[0] = pTemp[0*4] + pTemp[1*4]; a[1] = pTemp[0*4] - pTemp[1*4]; a[2] = pTemp[2*4] + pTemp[3*4]; a[3] = pTemp[2*4] - pTemp[3*4]; pTemp = pTemp++; ... } ... } The error was found through the V567 diagnostic: Undefined behavior. The 'pTemp' variable is modified while being used twice between sequence points. me umc_me_cost_func.h 168 This is a classic example of undefined program behavior. It is this construct which is used to demonstrate Undefined behavior in various articles. It is unknown whether 'pTemp' will be incremented by one or not. Two actions of changing pTemp variable's value are located in one sequence point. It means that the compiler may create the following code: pTemp = pTemp + 1; pTemp = pTemp; Стр. 14 из 46 28.10.2011 14:05
  • 15. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Or it may create another version of the code: TMP = pTemp; pTemp = pTemp + 1; pTemp = TMP; Which of the two code versions will be created depends on the compiler and optimization switches. Example 3. Fennec Media Project project. Complex expression. uint32 CUnBitArrayOld::DecodeValueRiceUnsigned(uint32 k) { ... while (!(m_pBitArray[m_nCurrentBitIndex >> 5] & Powers_of_Two_Reversed[m_nCurrentBitIndex++ & 31])) {} ... } The error was found through the V567 diagnostic: Undefined behavior. The 'm_nCurrentBitIndex' variable is modified while being used twice at single sequence point. MACLib unbitarrayold.cpp 78 There are no sequence points between two instances of using the 'm_nCurrentBitIndex' variable. It means that the standard does not specify the moment when this variable is incremented. Correspondingly, this code may work differently depending on the compiler and optimization switches. Example 4. Miranda IM project. Complex expression. short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len) { ... while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { ... } The error was found through the V567 diagnostic: Undefined behavior. The 's' variable is modified while being used twice between sequence points.msne zxml.c 371 Prefix increment of the variable is used here. But it does not mean anything: it cannot be guaranteed that the 's' variable will be incremented before calling the strspn() function. Errors relating to operation priorities. To make understanding of examples easier, let's recall the operation priorities table. Стр. 15 из 46 28.10.2011 14:05
  • 16. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Figure 7 - Operation priorities in C/C++ Example 1. MySQL project. Priorities of ! and & operations. int ha_innobase::create(...) { ... if (srv_file_per_table && !mysqld_embedded && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) { ... } The error was found through the V564 diagnostic: The '&' operator is applied to bool type value. You've probably forgotten to include parentheses or intended to use the '&&' operator. innobase ha_innodb.cc 6789 Стр. 16 из 46 28.10.2011 14:05
  • 17. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... The programmer wanted a part of the expression to check that a certain bit in the 'create_info->options' variable is equal to zero. But the priority of the '!' operation is higher than that of the '&' operation, that's why the expression works by this algorithm: ((!create_info->options) & HA_LEX_CREATE_TMP_TABLE) We should use additional parentheses if we want the code to work properly: (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) Or, what we find nicer, write the code in the following way: ((create_info->options & HA_LEX_CREATE_TMP_TABLE) == 0) Example 2. Emule project. Priorities of * and ++ operations. STDMETHODIMP CCustomAutoComplete::Next(..., ULONG *pceltFetched) { ... if (pceltFetched != NULL) *pceltFetched++; ... } The error was found through the V532 diagnostic: Consider inspecting the statement of '*pointer++' pattern. Probably meant: '(*pointer)++'. emule customautocomplete.cpp 277 If 'pceltFetched' is not a null pointer, the function must increment the variable of the ULONG type this pointer refers to. The error is this: the priority of the '++' operation is higher than that of '*' operation (pointer dereferencing). The "*pceltFetched++;" line is identical to the following code: TMP = pceltFetched + 1; *pceltFetched; pceltFetched = TMP; Virtually it is just increment of the pointer. To make the code correct, we must add parentheses: "(*pceltFetched)++;". Example 3. Chromium project. Priorities of & and != operations. #define FILE_ATTRIBUTE_DIRECTORY 0x00000010 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) { ... info->is_directory = file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0; ... } The error was found through the V564 diagnostic: The '&' operator is applied to bool type value. You've probably forgotten to include parentheses or intended to use the '&&' operator. base platform_file_win.cc 216 Programmers easily forget that the priority of the '!=' operation is higher than that of '&'. This is what happened in our case. As a result, we have the following expression: info->is_directory = file_info.dwFileAttributes & (0x00000010 != 0); Let's simplify the expression: Стр. 17 из 46 28.10.2011 14:05
  • 18. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... info->is_directory = file_info.dwFileAttributes & (true); Let's simplify it once again: info->is_directory = file_info.dwFileAttributes & 1; It turns out that we have tested the first bit instead of the fifth bit. To fix this, we need to add parentheses. Example 4. BCmenu project. IF and ELSE mixed up. void BCMenu::InsertSpaces(void) { if(IsLunaMenuStyle()) if(!xp_space_accelerators) return; else if(!original_space_accelerators) return; ... } The error was found through the V563 diagnostic: It is possible that this 'else' branch must apply to the previous 'if' statement. fire bcmenu.cpp 1853 This is not an error of operation priorities, but one relative to it. The programmer does not take into account that the 'else' branch refers to the nearest 'if' operator. We can see that the code justification as if it works by the following algorithm: if(IsLunaMenuStyle()) { if(!xp_space_accelerators) return; } else { if(!original_space_accelerators) return; } But actually it is equivalent to the following construct: if(IsLunaMenuStyle()) { if(!xp_space_accelerators) { return; } else { if(!original_space_accelerators) return; } } Example 5. IPP Samples project. Priorities of ?: and | operations. vm_file* vm_file_fopen(...) { ... mds[3] = FILE_ATTRIBUTE_NORMAL | (islog == 0) ? 0 : FILE_FLAG_NO_BUFFERING; ... } The error was found through the V502 diagnostic: Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '|' operator. vm vm_file_win.c 393 Depending on the 'islog' variable's value, the expression must be either equal to "FILE_ATTRIBUTE_NORMAL" or "FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING". But it does not happen. Priority of the '?:' operation is lower than that of '|'. As a result, the code acts as follows: Стр. 18 из 46 28.10.2011 14:05
  • 19. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... mds[3] = (FILE_ATTRIBUTE_NORMAL | (islog == 0)) ? 0 : FILE_FLAG_NO_BUFFERING; Let's simplify the expression: mds[3] = (0x00000080 | ...) ? 0 : FILE_FLAG_NO_BUFFERING; Since FILE_ATTRIBUTE_NORMAL equals 0x00000080, the condition is always true. It means that 0 will always be written into mds[3]. Example 6. Newton Game Dynamics project. Priorities of ?: and * operations. dgInt32 CalculateConvexShapeIntersection (...) { ... den = dgFloat32 (1.0e-24f) * (den > dgFloat32 (0.0f)) ? dgFloat32 (1.0f) : dgFloat32 (-1.0f); ... } The error was found through the V502 diagnostic: Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '*' operator. physics dgminkowskiconv.cpp 1061 The error in this code again relates to the low priority of the '?:' operation. The condition for the '?:' operator is expressed by a meaningless subexpression "dgFloat32 (1.0e-24f) * (den > dgFloat32 (0.0f))". Adding parentheses will solve the issue. By the way, programmers often forget how cunning the '?:' operator is. Here is a post on this topic: "How to make fewer errors at the stage of code writing. Part N2". Formatted output errors Examples of these errors are boring and alike, so we will examine only a few samples. The point is that functions with a variable number of arguments accept actual arguments incompatible with the format string. Any programmer who uses such functions as printf() is familiar with this type of errors. Example 1. ReactOS project. Incorrect printing of a WCHAR-character. static void REGPROC_unescape_string(WCHAR* str) { ... default: fprintf(stderr, "Warning! Unrecognized escape sequence: %c'n", str[str_idx]); ... } The error was found through the V576 diagnostic: Incorrect format. Consider checking the third actual argument of the 'fprintf' function. The char type argument is expected. regedit regproc.c 293 The fprinf() function must print a character of the char type. But the third argument is a character of the WCHAR type. The user will get an incorrectly generated message. To fix the code, we should replace '%c' with '%C' in the format string. Example 2. Intel AMT SDK project. Character '%' missing. Стр. 19 из 46 28.10.2011 14:05
  • 20. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... void addAttribute(...) { ... int index = _snprintf(temp, 1023, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" "%02x%02x:02x%02x:%02x%02x:%02x%02x", value[0],value[1],value[2],value[3],value[4], value[5],value[6],value[7],value[8], value[9],value[10],value[11],value[12], value[13],value[14],value[15]); ... } The error was found through the V576 diagnostic: Incorrect format. A different number of actual arguments is expected while calling '_snprintf' function. Expected: 18. Present: 19. mod_pvs mod_pvs.cpp 308 It is not easy to find an error here at first sight. However, the PVS-Studio analyzer does not get tired and notices that the function takes more actual arguments than specified in the format string. The reason is that the '%' character is missing in one place. Let's single out this fragment: "%02x%02x:[HERE]02x%02x:%02x%02x:%02x%02x", Example 3. Intel AMT SDK project. Unused argument. bool GetUserValues(...) { ... printf("Error: illegal value. Aborting.n", tmp); return false; } The error was found through the V576 diagnostic: Incorrect format. A different number of actual arguments is expected while calling 'printf' function. Expected: 1. Present: 2. RemoteControlSample remotecontrolsample.cpp 792 The error is this: the 'tmp' variable is not used in any way when printing the information message. Example 4. G3D Content Pak project. Printing of meaningless data. class Matrix3 { ... inline float* operator[] (int iRow) { ... }; void AnyVal::serialize(G3D::TextOutput& t) const { ... const Matrix3& m = *(Matrix3*)m_value; ... t.printf("%10.5f, %10.5f, %10.5f,n %10.5f, %10.5f, %10.5f,n %10.5f, %10.5f, %10.5f)", m[0, 0], m[0, 1], m[0, 2], m[1, 0], m[1, 1], m[1, 2], m[2, 0], m[2, 1], m[2, 2]); ... } The error was found through the V520 diagnostic: The comma operator ',' in array index expression '[0, 0]'. graphics3D anyval.cpp 275 Стр. 20 из 46 28.10.2011 14:05
  • 21. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... The program prints meaningless values instead of the matrix. You may write such a code when you work with different programming languages and sometimes forget how to access an item in a two-dimensional array in the C language. Let's see how the 'm[0, 1]' expression works. At first, expression"0, 1" is calculated. The result of this expression is 1. Then the 'operator[]' function is called in the Matrix3 class. The function takes the actual argument 1 and returns the pointer to the first string in the matrix. It is the value of this pointer that will be printed by the 'printf()' function though it expects a value of the float-type. This is the correct code: t.printf("%10.5f, %10.5f, %10.5f,n %10.5f, %10.5f, %10.5f,n %10.5f, %10.5f, %10.5f)", m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); Examples of misprints found in code A lot of programming errors are caused by misprints. Most of these errors are quickly detected at the early stages of testing. But there are some defects of this kind that remain in code for a long time causing troubles both to programmers and users. You can make these errors much fewer using the PVS-Studio analyzer. It will find them before testing starts, which will significantly reduce the cost of defect detection and elimination. Example 1. Miranda IM project. Assignment inside IF. void CIcqProto::handleUserOffline(BYTE *buf, WORD wLen) { ... else if (wTLVType = 0x29 && wTLVLen == sizeof(DWORD)) ... } The error was found through the V560 diagnostic: A part of conditional expression is always true: 0x29. icqoscar8 fam_03buddy.cpp 632 Because of a misprint, there is an assignment taking place inside the condition of the 'if' operator. This is the correct condition: "if (wTLVType == 0x29 && wTLVLen == sizeof(DWORD))". Example 2. ReactOS project. Assignment error. BOOL WINAPI GetMenuItemInfoA(...) { ... mii->cch = mii->cch; ... } The error was found through the V570 diagnostic: The 'mii->cch' variable is assigned to itself. user32 menu.c 4347 The value of the variable is assigned to itself. The programmer apparently intended to write it in this way: "mii->cch = miiW->cch;". Example 3. Clang project. Object name misprinted. Стр. 21 из 46 28.10.2011 14:05
  • 22. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... static Value *SimplifyICmpInst(...) { ... case Instruction::Shl: { bool NUW = LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap(); bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap(); ... } The error was found through the V501 diagnostic: There are identical sub-expressions 'LBO->hasNoUnsignedWrap ()' to the left and to the right of the '&&' operator. LLVMAnalysis instructionsimplify.cpp 1891 There is a misprint when using variables with similar names. In the first line, both LBO and RBO variables must be used. This is the correct code: bool NUW = LBO->hasNoUnsignedWrap() && RBO->hasNoUnsignedWrap(); Example 4. Notepad++ project. Incorrect state test. bool _isPointXValid; bool _isPointYValid; ... bool isPointValid() { return _isPointXValid && _isPointXValid; }; The error was found through the V501 diagnostic: There are identical sub-expressions to the left and to the right of the '&&' operator. _isPointXValid && _isPointXValid The name '_isPointXValid' is used twice. The function must actually return this code: "_isPointXValid && _isPointYValid". Example 5. StrongDC++ project. Unsuccessful check of rn. static void getContentLengthAndHeaderLength(...) { ... while(line[linelen] != 'r' && line[linelen] != 'r') ... } The error was found through the V501 diagnostic: There are identical sub-expressions 'line [linelen] != 'r'' to the left and to the right of the '&&' operator. miniupnpc miniupnpc.c 153 Because of a misprint, presence of the 'r' character is checked twice. Actually presence of the 'n' character must be checked too. Example 6. G3D Content Pak project. A closing parenthesis in a wrong place. bool Matrix4::operator==(const Matrix4& other) const { if (memcmp(this, &other, sizeof(Matrix4) == 0)) { return true; } ... } The error was found through the V575 diagnostic: The 'memcmp' function processes '0' elements. Inspect the 'third' argument. graphics3D matrix4.cpp 269 Стр. 22 из 46 28.10.2011 14:05
  • 23. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... One closing parenthesis is in a wrong place. It turns out that the size of the memory area being compared is calculated by the "sizeof(Matrix4) == 0" expression. This expression always has the 'false' result. Then 'false' turns into an integer value equal to 0. This is the correct code: if (memcmp(this, &other, sizeof(Matrix4)) == 0) { Example 7. QT project. Error of structure member copying. PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) { ... transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties; transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; ... } The error was found through the V570 diagnostic: The 'transition->m_hasGetterSetterProperties' variable is assigned to itself. QtScript structure.cpp 512 It is not easy to find an error looking at this code. But it is there. The field 'm_hasGetterSetterProperties' is copied into itself. This is the correct code: transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; Example 8. Apache HTTP Server project. Extra sizeof operator. PSECURITY_ATTRIBUTES GetNullACL(void) { PSECURITY_ATTRIBUTES sa; sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES)); sa->nLength = sizeof(sizeof(SECURITY_ATTRIBUTES)); ... } The error was found through the V568 diagnostic: It's odd that the argument of sizeof() operator is the 'sizeof (SECURITY_ATTRIBUTES)' expression. libhttpd util_win32.c 115 The field 'nLength' must contain the size of the 'SECURITY_ATTRIBUTES' structure. There is a misprint in the code: the 'sizeof' operator is used twice. As a result, the field 'nLength' stores a size of the 'size_t' type. This is the correct code: sa->nLength = sizeof(SECURITY_ATTRIBUTES); Example 9. FCE Ultra project. Double variable declaration. int iNesSaveAs(char* name) { ... fp = fopen(name,"wb"); int x = 0; if (!fp) int x = 1; Стр. 23 из 46 28.10.2011 14:05
  • 24. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... ... } The error was found through the V561 diagnostic: It's probably better to assign value to 'x' variable than to declare it anew. Previous daclaration: ines.cpp, line 960. fceuxines.cpp 962 The 'x' variable must store information whether or not a file was opened successfully. Because of a misprint, a new variable named 'x' is created and initialized instead of assigning 1 to the existing variable. This is how the correct code must look: if (!fp) x = 1; Example 10. Notepad++ project. Using && operator instead of &. TCHAR GetASCII(WPARAM wParam, LPARAM lParam) { ... result=ToAscii(wParam, (lParam >> 16) && 0xff, keys,&dwReturnedValue,0); ... } The error was found through the V560 diagnostic: A part of conditional expression is always true: 0xff. notepadPlus babygrid.cpp 694 The "(lParam >> 16) && 0xff" expression is meaningless and is always equal to 1 (true). A misprint here is in using the '&&' operator instead of '&'. Example 11. WinDjView project. Incomplete condition. inline bool IsValidChar(int c) { return c == 0x9 || 0xA || c == 0xD || c >= 0x20 && c <= 0xD7FF || c >= 0xE000 && c <= 0xFFFD || c >= 0x10000 && c <= 0x10FFFF; } The error was found through the V560 diagnostic: A part of conditional expression is always true: 0xA. WinDjView xmlparser.cpp 45 False The IsValidChar function always returns 'true'. Comparison is missing in one place because of a misprint: "... || 0xA || ...". Example 12. Fennec Media Project project. Extra semicolon. int settings_default(void) { ... for(i=0; i<16; i++); for(j=0; j<32; j++) { settings.conversion.equalizer_bands.boost[i][j] = 0.0; settings.conversion.equalizer_bands.preamp[i] = 0.0; } } The error was found through the V529 diagnostic: Odd semicolon ';' after 'for' operator. settings.c 483 All the C and C++ programmers know how dangerous an extra semicolon ';' is. Unfortunately, this Стр. 24 из 46 28.10.2011 14:05
  • 25. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... knowledge does not prevent them from making such misprints. There is an extra semicolon after the first 'for' operator, which makes this program fragment unable to execute. Example 13. QT project. Missing break operator. int QCleanlooksStyle::pixelMetric(...) { ... case PM_SpinBoxFrameWidth: ret = 3; break; case PM_MenuBarItemSpacing: ret = 6; case PM_MenuBarHMargin: ret = 0; break; ... } The error was found through the V519 diagnostic: The 'ret' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 3765, 3767. QtGui qcleanlooksstyle.cpp 3767 This is a classic error - 'break' is missing inside the 'switch' operator. I think you do not need any further comments here. Example 14. Miranda IM project. Assignment instead of comparison. int FindItem(...) { ... int ret; ret=FindItem(hwnd,dat,hItem, (struct ClcContact ** )&z, (struct ClcGroup ** )&isv,NULL); if (ret=0) {return (0);} ... } The error was found through the V559 diagnostic: Suspicious assignment inside the condition expression of 'if' operator: ret = 0. clist_mw clcidents.c 179 There is a misprint inside the condition of the 'if' operator: '=' is written instead of '=='. The function will handle the situation incorrectly when a certain item is not found. Example 15. IPP Samples project. Incorrect index. struct AVS_MB_INFO { ... Ipp8u refIdx[AVS_DIRECTIONS][4]; ... }; void AVSCompressor::GetRefIndiciesBSlice(void){ ... if (m_pMbInfo->predType[0] & predType) { m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][0]; iRefNum += 1; } if (m_pMbInfo->predType[1] & predType) { Стр. 25 из 46 28.10.2011 14:05
  • 26. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][1]; iRefNum += 1; } if (m_pMbInfo->predType[2] & predType) { m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][2]; iRefNum += 1; } if (m_pMbInfo->predType[3] & predType) { m_refIdx[iRefNum] = m_pMbInfo->refIdx[dir][30]; iRefNum += 1; } ... } The error was found through the V557 diagnostic: Array overrun is possible. The '30' index is pointing beyond array bound. avs_enc umc_avs_enc_compressor_enc_b.cpp 495 Consider this fragment: "m_pMbInfo->refIdx[dir][30]". Because of a misprint, number 30 is written instead of index 3. By the way, this sample shows well how relative our division of errors into categories is. This error might well be referred to the category "Errors of array and string handling". The division is relative and is made to show diversity of errors the PVS-Studio analyzer can detect. Example 16. ReactOS project. Misprint in a macro. #define SWAP(a,b,c) c = a; a = b; a = c The error was found through the V519 diagnostic: The 'v2' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 343, 343. win32k gradient.c 343 It is a rather funny misprint in a macro intended to swap values in two variables. Look closely at the code and you will see what I mean. This is the correct code: #define SWAP(a,b,c) c = a; a = b; b = c This time we did not manage to stop at the 13-th example: so many errors in software are caused by misprints. There are much more errors of this kind than programmers think. We could go on and on in this section but we decide to stop at the 16-th example at last. Incorrect use of base functions and classes Example 1. Fennec Media Project. Two terminal nulls absent. int JoiningProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam) { ... OPENFILENAME lofn; memset(&lofn, 0, sizeof(lofn)); ... lofn.lpstrFilter = uni("All Files (*.*)0*.*"); ... } The error was found through the V540 diagnostic: Member 'lpstrFilter' should point to string terminated Стр. 26 из 46 28.10.2011 14:05
  • 27. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... by two 0 characters. base windows.c 5309 In Windows API there are structures in which pointers to strings must end with two null characters. It is that very kind of string the 'lpstrFilter' member in the OPENFILENAME structure points to. Description of 'lpstrFilter' in MSDN: LPCTSTR A buffer containing pairs of null-terminated filter strings. The last string in the buffer must be terminated by two NULL characters. If you forget to write an additional null at the end, the dialogue of file handling may contain garbage in the filter fields. This is the correct code: lofn.lpstrFilter = uni("All Files (*.*)0*.*0"); Example 2. TortoiseSVN project. Incorrect use of 'remove' function. STDMETHODIMP CShellExt::Initialize(....) { ... ignoredprops = UTF8ToWide(st.c_str()); // remove all escape chars ('') std::remove(ignoredprops.begin(), ignoredprops.end(), ''); break; ... } The error was found through the V530 diagnostic: The return value of function 'remove' is required to be utilized. contextmenu.cpp 442 The std::remove function does not remove items from the container. It only shifts the items and returns the iterator to the beginning of trash. Assume we have a vector<int> container that contains items 1,2,3,1,2,3,1,2,3. If we execute the code "remove( v.begin(), v.end(), 2 )", the container will contain items 1,3,1,3,X,X,X, where X is some trash. The function will return the iterator to the first trash item, so if we want to remove these trash items, we need to write the code: "v.erase(remove(v.begin(), v.end(), 2), v.end())". Example 3. TortoiseSVN project. Using 'empty' function instead of 'clear'. CMailMsg& CMailMsg::SetFrom(string sAddress, string sName) { if (initIfNeeded()) { // only one sender allowed if (m_from.size()) m_from.empty(); m_from.push_back(TStrStrPair(sAddress,sName)); } return *this; } The error was found through the V530 diagnostic: The return value of function 'empty' is required to be utilized. mailmsg.cpp 40 The error here is this: the vector::empty() function is called by mistake instead of vector::clear(), and the array's contents remain the same. It is a very frequent error because the words 'clear' and 'empty' are rather Стр. 27 из 46 28.10.2011 14:05
  • 28. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... close in meaning, and you might easily mix them up. Example 4. WinMerge project. Using 'empty' function instead of 'clear'. void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) const { UINT_PTR diffpos = GetItemKey(sel); if (diffpos == (UINT_PTR)SPECIAL_ITEM_POS) { strLeft.empty(); strRight.empty(); } else { ... } } The error was found through the V530 diagnostic: The return value of function 'empty' is required to be utilized WinMerge DirActions.cpp 1307, 1308 Again, the reason is in using the empty() function instead of clear(). We could cite examples of such errors from other projects as well: InstantVNC, IPP Samples, Chromium, Intel AMT SDK, etc. Unfortunately, all these samples are alike, and there is nothing interesting about examining them. But trust me, you can see these defects in serious projects developed by professional programmers. Example 5. Pixie project. Using 'alloca' function inside loops. inline void triangulatePolygon(...) { ... for (i=1;i<nloops;i++) { ... do { ... do { ... CTriVertex *snVertex = (CTriVertex *)alloca(2*sizeof(CTriVertex)); ... } while(dVertex != loops[0]); ... } while(sVertex != loops[i]); ... } ... } The error was found through the V505 diagnostic: The 'alloca' function is used inside the loop. This can quickly overflow stack. ri polygons.cpp 1120 The alloca function allocates memory inside the stack, so calling it many times inside the loop body may suddenly cause a stack overflow. And we have several nested loops here. This code may exhaust stack memory very quickly. Example 6. Miranda IM project. Arguments mixed up. static BOOL ImageArray_Alloc(LP_IMAGE_ARRAY_DATA iad, int size) { ... memset(&iad->nodes[iad->nodes_allocated_size], Стр. 28 из 46 28.10.2011 14:05
  • 29. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... (size_grow - iad->nodes_allocated_size) * sizeof(IMAGE_ARRAY_DATA_NODE), 0); ... } The error was found through the V575 diagnostic: Function receives an odd argument. clist_modern modern_image_array.cpp 59 The 'memset' function handles 0 items, i.e. actually does nothing. The reason is in mixed up arguments. This is how the correct call of the memset function should be written: memset(&iad->nodes[iad->nodes_allocated_size], 0, (size_grow - iad->nodes_allocated_size) * sizeof(IMAGE_ARRAY_DATA_NODE)); Examples of meaningless code Example 1. IPP Samples project. Incomplete condition. void lNormalizeVector_32f_P3IM(Ipp32f *vec[3], Ipp32s* mask, Ipp32s len) { Ipp32s i; Ipp32f norm; for(i=0; i<len; i++) { if(mask<0) continue; norm = 1.0f/sqrt(vec[0][i]*vec[0][i]+ vec[1][i]*vec[1][i]+vec[2][i]*vec[2][i]); vec[0][i] *= norm; vec[1][i] *= norm; vec[2][i] *= norm; } } The error was found through the V503 diagnostic: This is a nonsensical comparison: pointer < 0. ipprsample ippr_sample.cpp 501 I do not know how it happened, but there are 3 characters "[i]" missing in this code. As a result, the code performs a meaningless check that the pointer is below zero instead of checking the mask array. The correct check should be written in this way: if(mask[i] < 0). Example 2. Pc Ps2 Emulator project. Incorrect switch. LRESULT CALLBACK IOP_DISASM(...) { ... switch(LOWORD(wParam)) { case (IDOK || IDCANCEL): EndDialog(hDlg,TRUE); return(TRUE); break; } ... } The error was found through the V560 diagnostic: A part of conditional expression is always true: 2. pcsx2 debugger.cpp 321 Стр. 29 из 46 28.10.2011 14:05
  • 30. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... This code does not have any meaning. The programmer must have intended to write it this way: switch(LOWORD(wParam)) { case IDOK: //no break case IDCANCEL: EndDialog(hDlg,TRUE); return(TRUE); break; } Example 3. CPU Identifying Tool project. A too strict condition. void projillum(short* wtab, int xdots, int ydots, double dec) { ... s = sin(-dtr(dec)); x = -s * sin(th); y = cos(th); ... lon = (y == 0 && x == 0) ? 0.0 : rtd(atan2(y, x)); } The error was found through the V550 diagnostic: An odd precise comparison: x == 0. It's probably better to use a comparison with defined precision: fabs(A - B) '<' Epsilon. clock_dll sunalgo.cpp 155 It is strange to expect that the result will be strictly 0 after executing all these complex calculations using 'sin' and 'cos' functions. Most likely, there must be comparison to be performed with certain accuracy. Example 4. Lugaru. Double assignment. int Game::DrawGLScene(void) { ... radius=fast_sqrt(maxdistance); radius=110; ... } The error was found through the V519 diagnostic: The 'radius' object is assigned values twice successively. Perhaps this is a mistake. Lugaru gamedraw.cpp 1505 The programmer must have deliberately written value 110 into the 'radius' variable for the sake of experiment and then forgot to remove this line. As a result, we have a meaningless and maybe even invalid code. Example 5. QT project. Duplicated check. Q3TextCustomItem* Q3TextDocument::parseTable(...) { ... while (end < length && !hasPrefix(doc, length, end, QLatin1String("</td")) && !hasPrefix(doc, length, end, QLatin1String("<td")) && !hasPrefix(doc, length, end, QLatin1String("</th")) && !hasPrefix(doc, length, end, QLatin1String("<th")) && !hasPrefix(doc, length, end, QLatin1String("<td")) && !hasPrefix(doc, length, end, QLatin1String("</tr")) && !hasPrefix(doc, length, end, QLatin1String("<tr")) && !hasPrefix(doc, length, end, QLatin1String("</table"))) { ... Стр. 30 из 46 28.10.2011 14:05
  • 31. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... } The error was found through the V501 diagnostic: There are identical sub-expressions to the left and to the right of the '&&' operator. Qt3Support q3richtext.cpp 6978 Presence of the "<td" prefix is checked twice in the condition. It is meaningless. Maybe it is an extra check or there should be some other prefix instead of the second "<td". Example 6. Audacity project. Strange check. int sf_error (SNDFILE *sndfile) { ... if (!sndfile) { if (sf_error != 0) return sf_errno; return 0; } ; ... } The error was found through the V516 diagnostic: Consider inspecting an odd expression. Non-null function pointer is compared to null: 'sf_error != 0'. libsndfile sndfile.c 491 The "sf_error != 0" check always returns true, since 'sf_error' is the name of the function in which the code is executed. Example 7. IPP Samples project. Strange code inside a loop. static IppStatus mp2_HuffmanTableInitAlloc(Ipp32s *tbl, ...) { ... for (i = 0; i < num_tbl; i++) { *tbl++; } ... } The error was found through the V532 diagnostic: Consider inspecting the statement of '*pointer++' pattern. Probably meant: '(*pointer)++'. mpeg2_dec umc_mpeg2_dec.cpp 59 The loop body is probably incomplete because it is meaningless in the current form. Always true or always false conditions It is a very large and widely-spread type of errors. These errors also vary greatly depending on the importance level. To non-dangerous errors we may refer incorrect conditions in ASSERT that actually do not check anything. To dangerous errors, incorrect checks of buffer size or index size are referred. Example 1. Shareaza project. Value range of char type. void CRemote::Output(LPCTSTR pszName) { ... CHAR* pBytes = new CHAR[ nBytes ]; hFile.Read( pBytes, nBytes ); ... if ( nBytes > 3 && pBytes[0] == 0xEF && Стр. 31 из 46 28.10.2011 14:05
  • 32. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... pBytes[1] == 0xBB && pBytes[2] == 0xBF ) { pBytes += 3; nBytes -= 3; bBOM = true; } ... } The error was found through the V547 diagnostic: Expression 'pBytes [ 0 ] == 0xEF' is always false. The value range of signed char type: [-128, 127]. Shareaza remote.cpp 350 In this code, the 'TCHAR' type is the 'char' type. The value range of char is from -128 to 127 inclusive. Value 0xEF in the variable of the char type is nothing else than number -17. When comparing the char variable with number 0xEF, its type is extended up to the 'int' type. But the value still lies inside the range [-128..127]. The "pBytes[0] == 0xEF" ("-17 == 0xEF") condition is always false, and the program does not work as intended. This is the correct comparison: if ( nBytes > 3 && pBytes[0] == TCHAR(0xEF) && pBytes[1] == TCHAR(0xBB) && pBytes[2] == TCHAR(0xBF) ) Example 2. TortoiseSVN project. Value range of char type. BOOL TortoiseBlame::OpenFile(const TCHAR *fileName) { ... // check each line for illegal utf8 sequences. // If one is found, we treat // the file as ASCII, otherwise we assume // an UTF8 file. char * utf8CheckBuf = lineptr; while ((bUTF8)&&(*utf8CheckBuf)) { if ((*utf8CheckBuf == 0xC0)|| (*utf8CheckBuf == 0xC1)|| (*utf8CheckBuf >= 0xF5)) { bUTF8 = false; break; } ... } ... } The error was found through the V547 diagnostic: Expression '* utf8CheckBuf == 0xC0' is always false. The value range of signed char type: [-128, 127]. tortoiseblame.cpp 310 While the defect in the previous example seems to be caused through mere inattention, in this case it is not so. Here is another identical example where a condition is always false. This is a very widely-spread type of errors in various projects. Example 3. VirtualDub project. Unsigned type is always >= 0. typedef unsigned short wint_t; ... void lexungetc(wint_t c) { Стр. 32 из 46 28.10.2011 14:05
  • 33. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... if (c < 0) return; g_backstack.push_back(c); } The error was found through the V547 diagnostic: Expression 'c < 0' is always false. Unsigned type value is never < 0. Ami lexer.cpp 225 The "c < 0" condition is always false because the variable of the unsigned type is always above or equal to 0. Example 4. Swiss-Army Knife of Trace project. Socket handling. static UINT_PTR m_socketHandle; void TTrace::LoopMessages(void) { ... // Socket creation if ( (m_socketHandle = socket(AF_INET,SOCK_STREAM,0)) < 0) { continue; } ... } The error was found through the V547 diagnostic: Expression '(m_socketHandle = socket (2, 1, 0)) < 0' is always false. Unsigned type value is never < 0. Vs8_Win_Lib tracetool.cpp 871 An attempt to check that a socket was created successfully is performed incorrectly. If a socket cannot be created, this situation is not handled in any way. To make the check work correctly, we should use the INVALID_SOCKET constant: m_socketHandle = socket(AF_INET,SOCK_STREAM,0); if (m_socketHandle == INVALID_SOCKET) Example 5. Chromium project. Time handling. IdleState CalculateIdleState(...) { ... DWORD current_idle_time = 0; ... // Will go -ve if we have been idle for // a long time (2gb seconds). if (current_idle_time < 0) current_idle_time = INT_MAX; ... } The error was found through the V547 diagnostic: Expression 'current_idle_time < 0' is always false. Unsigned type value is never < 0. browser idle_win.cc 23 To handle time, a variable of the unsigned type is used. As a result, check of too large values does not work. This is the correct code: if (current_idle_time > INT_MAX) current_idle_time = INT_MAX; Example 6. ICU project. Error in condition. U_CDECL_BEGIN static const char* U_CALLCONV Стр. 33 из 46 28.10.2011 14:05
  • 34. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... _processVariableTop(...) { ... if(i == locElementCapacity && (*string != 0 || *string != '_')) { *status = U_BUFFER_OVERFLOW_ERROR; } ... } The error was found through the V547 diagnostic: Expression '*string != 0 || *string != '_'' is always true. Probably the '&&' operator should be used here. icui18n ucol_sit.cpp 242 The condition contains a logical error. The "(*string != 0 || *string != '_')" subexpression is always true. It is impossible that one and the same string character is not equal to 0 and '_' at a time. Example 7. QT project. Dangerous loop. bool equals( class1* val1, class2* val2 ) const{ { ... size_t size = val1->size(); ... while ( --size >= 0 ){ if ( !comp(*itr1,*itr2) ) return false; itr1++; itr2++; } ... } The error was found through the V547 diagnostic: Expression '--size >= 0' is always true. Unsigned type value is always >= 0. QtCLucene arrays.h 154 The (--size >= 0) condition is always true, since the size variable has the unsigned type. It means that if two sequences being compared are alike, we will get an overflow that will in its turn cause Access Violation or other program failures. This is the correct code: for (size_t i = 0; i != size; i++){ if ( !comp(*itr1,*itr2) ) return false; itr1++; itr2++; } Example 8. MySQL project. Error in condition. enum enum_mysql_timestamp_type str_to_datetime(...) { ... else if (str[0] != 'a' || str[0] != 'A') continue; /* Not AM/PM */ ... } The error was found through the V547 diagnostic: Expression 'str [0] != 'a' || str [0] != 'A'' is always true. Probably the '&&' operator should be used here. clientlib my_time.c 340 Стр. 34 из 46 28.10.2011 14:05
  • 35. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... The condition is always true because the character is always either not equal to 'a' or to 'A'. This is the correct check: else if (str[0] != 'a' && str[0] != 'A') Example 9. QT project. Incorrect count of references. STDMETHODIMP QEnumPins::QueryInterface(const IID &iid,void **out) { ... if (S_OK) AddRef(); return hr; } The error was found through the V545 diagnostic: Such conditional expression of 'if' operator is incorrect for the HRESULT type value '(HRESULT) 0L'. The SUCCEEDED or FAILED macro should be used instead. phonon_ds9 qbasefilter.cpp 60 The check condition is represented by the S_OK constant. Since S_OK is 0, the AddRef() function will never be called. This is how this check must look: if (hr == S_OK). Example 10. TickerTape project. Incorrect tornado. void GetWindAtSingleTornado(...) { ... if(radius < THRESH * 5) *yOut = THRESH * 10 / radius; else if (radius < THRESH * 5) *yOut = -3.0f / (THRESH * 5.0f) * (radius - THRESH * 5.0f) + 3.0f; else *yOut = 0.0f; ... } The error was found through the V517 diagnostic: The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. TickerTape wind.cpp 118 The second condition is always false. The reason is that the first condition coincides with the second. There must be a misprint here. Example 11. Apache HTTP Server project. Error of socket handling in Windows. typedef UINT_PTR SOCKET; static unsigned int __stdcall win9x_accept(void * dummy) { SOCKET csd; ... do { clen = sizeof(sa_client); csd = accept(nsd, (struct sockaddr *) &sa_client, &clen); } while (csd < 0 && APR_STATUS_IS_EINTR(apr_get_netos_error())); ... } The error was found through the V547 diagnostic: Expression 'csd < 0' is always false. Unsigned type value is never < 0. libhttpd child.c 404 Стр. 35 из 46 28.10.2011 14:05
  • 36. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... Socket handling errors very often emerge in crossplatform programs built under Windows. In Linux, socket descriptors are represented by the signed type, while in Windows it is the unsigned type. Programmers often forget about this and check the error status by comparing the value to 0. This is incorrect; you must use specialized constants. Example 12. QT project. Misprint in comparisons. QStringList ProFileEvaluator::Private::values(...) { ... else if (ver == QSysInfo::WV_NT) ret = QLatin1String("WinNT"); else if (ver == QSysInfo::WV_2000) ret = QLatin1String("Win2000"); else if (ver == QSysInfo::WV_2000) <<-- ret = QLatin1String("Win2003"); else if (ver == QSysInfo::WV_XP) ret = QLatin1String("WinXP"); ... } The error was found through the V517 diagnostic: The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 2303, 2305. lrelease profileevaluator.cpp 2303 In the string we have marked, there must be the text "ver == QSysInfo::WV_2003". Because of this error, the "ret = QLatin1String("Win2003")" statement will never be executed. Code vulnerabilities Of course, errors leading to code vulnerabilities are actually misprints, incorrect conditions and incorrect array handling. But we decided to single out certain errors into a separate group because they relate to the notion of software vulnerabilities. An intruder, using such errors, can try to disturb program operation, perform an attack to gain extended rights or carry out any other actions he/she needs. Example 1. Ultimate TCP/IP project. Incorrect check of an empty string. char *CUT_CramMd5::GetClientResponse(LPCSTR ServerChallenge) { ... if (m_szPassword != NULL) { ... if (m_szPassword != '0') { ... } The error was found through the V528 diagnostic: It is odd that pointer to 'char' type is compared with the '0' value. Probably meant: *m_szPassword != '0'. UTMail ut_crammd5.cpp 333 This code fragment must check that the pointer to the password is not equal to NULL and that the string is not empty. But instead, the code checks twice that the pointer is not equal to NULL. The check of the string does not work. The "if (m_szPassword != '0')" condition was intended to check that there is a terminal null in the very beginning of the string, which means that the string is empty. But a pointer dereferencing operation is missing here, and it is the pointer itself which is compared to zero. This is the correct code: Стр. 36 из 46 28.10.2011 14:05
  • 37. PVS-Studio advertisement - static analysis of C/C++ code file:///C:/Users/evg/Documents/SVN/docx/new_docx/articles/code-ana... if (m_szPassword != NULL) { ... if (*m_szPassword != '0') Example 2. Chromium project. Null pointer handling. bool ChromeFrameNPAPI::Invoke(...) { ChromeFrameNPAPI* plugin_instance = ChromeFrameInstanceFromNPObject(header); if (!plugin_instance && (plugin_instance->automation_client_.get())) return false; ... } The error was found through the V522 diagnostic: Dereferencing of the null pointer 'plugin_instance' might take place. Check the logical condition. chrome_frame_npapi chrome_frame_npapi.cc 517 The condition that checks the null pointer is written incorrectly. As a result, we have a segmentation error. This is the correct code: if (plugin_instance && (plugin_instance->automation_client_.get())) return false; Example 3. SMTP Client with SSL/TLS project. Incomplete buffer clearing. void MD5::finalize () { ... uint1 buffer[64]; ... // Zeroize sensitive information memset (buffer, 0, sizeof(*buffer)); ... } The error was found through the V512 diagnostic: A call of the 'memset' function will lead to a buffer overflow or underflow. CSmtp md5.cpp 212 For security purposes, the function tries to clear the buffer containing sensitive information. But it fails. Only the first byte will be cleared in the buffer. The error is this: the 'sizeof' operator calculates the size of the 'uint1' type instead of buffer. This is the correct code: memset (buffer, 0, sizeof(buffer)); Generally, errors of incomplete memory clearing are rather frequent. Consider some other cases like this. Example 4. Chromium. Incomplete buffer clearing. void Time::Explode(..., Exploded* exploded) const { ... ZeroMemory(exploded, sizeof(exploded)); ... } The error was found through the V512 diagnostic: A call of the 'memset' function will lead to underflow of the buffer '(exploded)'. base time_win.cc 227 The ZeroMemory function clears only part of the Exploded structure. The reason is that the 'sizeof' Стр. 37 из 46 28.10.2011 14:05