Testing of Linux-applications with the help of PVS-Studio in Windows

06.08.2009 Evgeniy Ryzhkov

Quite recently we have released a new program product PVS-Studio which united our two analyzers Viva64 and VivaMP. When Viva64 analyzer intended for developers of 64-bit applications was a separate product yet, we were asked this question: "Is there a version of Viva64 for Linux?". And although it is possible to create such a version (as development of a separate solution for a particular client) there is no Linux-version of the analyzer for the moment.

But sometimes you can test the code of Linux-applications in 64-bit Linux environment in Windows system. It is this possibility our engineers are working at. In this note I will tell you how it works.

From the viewpoint of developing 64-bit applications Windows and Linux operation systems differ in the data model being used. This is a correlation between the sizes of basic data types in a particular system. In the 64-bit Windows-version LLP64 data model is used. In this data model the types have the following sizes: int - 32 bits, long - 32 bits, long long - 64 bits, size_t - 64 bits, pointer - 64 bits. In the 64-bit Linux-version LP64 data model is used. In it the data types' sizes are the following: int - 32 bits, long - 64 bits, long long - 64 bits, size_t - 64 bits, pointer - 64 bits. For 64-bit Linux and Windows systems such types as long double are also different but it is not relevant here. As you can see, the basic difference is in the size of long type - in 64-bit Windows it is 32 bits and in 64-bit Linux it is 64 bits.

By default, Viva64 code analyzer (and now PVS-Studio) is oriented on LLP64 data model being intended for operation in Windows environment. Roughly speaking, it means that it searches incorrect shared use of size_t-types and int-types. To test the code on correctness in 64-bit Linux-environment you need to search incorrect shared use of long-types and int-types as well.

We plan to add the possibility of searching incorrect shared use of long-types into the new version of PVS-Studio 3.10. It will be a special operation mode, the so called "Linux-like mode". The analyzer of 64-bit problems will operate in this mode in the same way as it would operate in Linux-environment. It will allow you to partly test the code of applications operating in Linux in Windows system with the help of PVS-Studio.

So, to test a 64-bit Linux-application you will need to have its version compiled into Visual Studio. That is, such testing is reasonable for cross-platform applications which are built both in Windows and Linux.

Of course, testing of an application on 64-bit code correctness in the mode of imitating Linux-environment cannot be considered full and guarantee its efficiency in real Linux-world. Besides, there can be more false responses. But in some cases this testing variant will help you find a lot of errors which would occur in 64-bit Linux-systems.

The disadvantage of this approach is code sections which are not built for Windows. For example, it can be interface parts of a program. You cannot test them in Windows because you cannot compile them. But, for example, you can test the core of a program which operates both in Windows and Linux.

You should also keep in mind that in Linux-like data model only user code is tested. The code included into system include-files in Windows will still be the same as for LLP64 memory model. For all the files are processed by the preprocessor before analysis and of course it does not know about LP64 model.

To demonstrate the peculiarities of using PVS-Studio in "Linux-like mode" I will give some examples.

void foo(ptrdiff_t delta);
int i = -2;
unsigned k = 1;
foo(i + k);

This code will be potentially unsafe both for Windows and Linux systems. An incorrect result occurs at implicit extension of the actual argument having the value 0xFFFFFFFF of unsigned type to ptrdiff_t type. In this case the warning will be shown independently from the mode being used.

void *ptr;
long np = (long)(ptr);

This code diagnosed as incorrect in 64-bit Windows programs will be correct for 64-bit Linux-systems.

Vice versa, the next example shows the code correct for Windows systems and incorrect for Linux ones:

long array[4] = { 1, 2, 3, 4 };
enum ENumbers { ZERO, ONE, TWO, THREE, FOUR };
int *intPtr = (int *)(array);
cout << intPtr[1] << endl;

As the sizes of int and long in 64-bit Linux systems do not coincide, the analyzer will show the corresponding diagnostic warning.

The last two examples demonstrate the limitations of the new operation mode:

#ifdef _WINDOWS
  typedef long MY_SIGNED_32;
#else //Linux
  typedef int MY_SIGNED_32;
#endif

As the preprocessor will choose the branch "typedef long MY_SIGNED_32;" all the code constructions containing MY_SIGNED_32 type will be incorrect from the viewpoint of Linux systems.

And finally we can give a simpler example when the code we need to analyze will not be analyzed:

#ifdef LINUX_64
   // there is too much code here
#endif

Despite the limitations we have listed, the ability of working both with the Windows-traditional LLP64 data model and Linux-traditional LP64 data model will help you broaden the scope of use of our code analyzer. You should just understand how this option operates and what it can and cannot provide.

By default, the new mode will be switched off and those users for whom operation in Linux-environment is not relevant, can forget about it.