Why do some static analysis tools not report potential buffer overflows? - static-analysis

I have an example of a strcpy command that seems to be a risk of a buffer overflow, but PVS-Studio doesn’t raise a warning. In my example, strcpy is used to copy a command line argument into a buffer, without checking the size of the command line argument. This could result in a buffer overflow if the argument exceeds the size of the buffer.
Code example:
char carg1[13];
int main(int argc, char* argv[])
{
// Get name from the 1st command line arg
strcpy(carg1, argv[1]);
…
}
The size of argv[1] isn't checked before being coping into carg1. Shouldn’t this raise a warning?

It's theoretically impossible to build a perfect static analysis tool (this follows from results like the undecidability of the halting problem). As a result, all static analysis tools are at best heuristics that can try to detect certain classes of errors, and even then can't necessarily detect all of those errors.
So yes, the code you've got above looks like it has a potential buffer overflow. I honestly don't know why this particular tool can't detect the error, but my guess is that the internal heuristics the analyzer uses for some reason is failing to detect it.
Hope this helps!

There are 3 facts:
1) If you use Visual C++ compiler then you will receive compiler warnings 4996.
1>robust.cpp(529): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\string.h(110) : see declaration of 'strcpy'
2) PVS-Studio initially worked with Visual Studio only.
3) PVS-Studio policy is to implement diagnostic rules which are not duplicate compiler warnings.
So it is seems a logical that PVS doesn't check the case which are already was checked by Microsoft compiler for a long time already (from VS2005).
Updated:
Finally PVS implemented such diagnostic rule:
https://www.viva64.com/en/w/V755/print/

Related

Expression must have a constant value error in array via MPI world size

Recently, i started learning about MPI programming and I have tried to program it on both Linux and Windows OS. I do not have any problem running the MPI application on Linux, however, i stumbled upon expression must have a constant value error on Visual Studio
For example, i'm trying to get the world_size via the MPI_Comm_size(MPI_COMM_WORLD, &world_size); and create an array based on the world_size (for example)
Code Sample :
#include <mpi.h>
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int database[world_size]; //error occured here
However, when i'm running it on Linux, it is working perfectly fine as i'm able to execute the code while stating the number of processes i wish to have. Am i missing out anything? I followed this particular youtube link that taught me how to install MS-MPI on my Visual Studio 2015.
Any help would be greatly appreciated.
Automatic array sizing using non const values actually works with gcc (https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html). However, it's considered a bad idea because (as you've just experienced) your code won't be portable anymore. You just need to change your code to create an array using new. You might want to generate an error to make sure your code is portable: Disable variable-length automatic arrays in gcc

Prevent Xcode/clang from raising logic error on intentionally flawed code

For testing purposes only, I'm including a function to intentionally crash my app (testing my app's handling of unintentional crashes). To do so, I'm using:
strcpy(0, "crash");
Of course, when doing analysis of my code, Xcode reports the logic error Null pointer argument in call to string copy function. I've tried wrapping the offending code like so:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
strcpy(0, "crash");
#pragma clang diagnostic pop
But Xcode (v9.2 (9C40b)) still complains (this isn't a warning, it's a logic error, I understand). Is there some other way to keep Xcode/clang from flagging this code? Is there some better way to induce a crash that can be protected from Xcode/clang analysis error?
This worked for me (no need to wrap in warning suppressions). It passes Xcode/clang's analysis and still results in the crash I want:
char *x = (char *)#"0".integerValue; strcpy(x, "crash");
How about volatile char* x=0; strcpy(x, "crash")
This'll work because the compiler isn't allowed to assume that x when read will be any value; meaning any checks that it might have hard coded should be ignored.
It seems to me that the best way to defeat static analysis is to do something dynamic. Objective-C, by its very nature, has lots of options for that, since the compiler can't guarantee a 1-to-1 correspondence between a message send and a method.
The simplest thing to do is probably to trigger an indexing error:
[#"" characterAtIndex:0]; // or
[#[] objectAtIndex:0];
Even if the analyzer knew that the default implementations of those methods raised an exception for out-of-bounds access, it can't know that you haven't swapped them out at runtime for an implementation that handles the problem gracefully.

Errors in OpenCL kernel code at runtime

I am new to Visual Studio and I am using it to write a simple parallel sorting program using OpenCL.
When I run it, I get a line before my output (i.e. from before I receive and print the result buffer) saying "5 Errors Generated.".
I assume this is telling me that I have errors in my kernel file, and if I deliberately write errors in my kernel file that number increases.
I would really like to know what those errors are so I can correct my program. Being unfamiliar with VS I simply cannot find them listed anywhere.
Does anyone know where I can find what errors are being generated.
Thanks
You need to call clGetProgramBuidlInfo asking for the CL_PROGRAM_BUILD_LOG in order to get the runtime errors of the compiler.
char result[4096];
size_t size;
clGetProgramBuildInfo( program, device, CL_PROGRAM_BUILD_LOG, sizeof(result), result, &size);
printf("%s\n", result);

Visual Studio: Debug before main() function call

I'm having an issue where my application is failing a debug assertion (_CrtIsValidHeapPointer) before anything is even executed. I know this because I added a breakpoint on the first statement of my main function, and it fails the assertion before the breakpoint is reached.
Is there a way to somehow "step through" everything that happens before my main function is called? Things like static member initializations, etc.
I should note that my program is written in C++/CLI. I recently upgraded to VS2015 and am targeting the v140 toolset. The C++ libraries I'm using (ImageMagick, libsquish, and one of my own C++ libraries) have been tested individually, and I do not receive the assertion failure with these libraries, so it has to be my main application.
I haven't changed any of the code since I upgraded from VS2013, so I'm a little stumped on what is going on.
EDIT:
Here is the call stack. This is after I click "Retry" in the assertion failed window. I then get a multitude of other exceptions being thrown, but they are different each time I run the program.
> ucrtbased.dll!527a6853()
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!527a7130()
ucrtbased.dll!527a69cb()
ucrtbased.dll!527c8116()
ucrtbased.dll!527c7eb3()
ucrtbased.dll!527c7fb3()
ucrtbased.dll!527c84b0()
PathCreator.exe!_onexit(int (void)* const function) Line 268 + 0xe bytes C++
PathCreator.exe!atexit(void (void)* const function) Line 276 + 0x9 bytes C++
PathCreator.exe!std::`dynamic initializer for '_Fac_tidy_reg''() Line 65 + 0xd bytes C++
[External Code]
mscoreei.dll!7401cd87()
mscoree.dll!741fdd05()
kernel32.dll!76c33744()
ntdll.dll!7720a064()
ntdll.dll!7720a02f()
You have to debug the C runtime initialization code. Not intuitive to do because the debugger tries hard to avoid it and get you into the main() entrypoint instead. But still possible, use Debug > New Breakpoint > Function Breakpoint.
Enter _initterm for the function name, Language = C.
Press F5 and the breakpoint will hit. You should see the C runtime source code. You can now single-step through the initialization functions of your program one-by-one, every call to (**it)() executes one.
That's exactly what you asked for. But not very likely what you actually want. The odds that your code produces this error are very low. Much more likely is that one of these libraries causes this problem. They are likely to be built targeting another version of the C runtime library. And therefore have their own _initterm() function.
Having more than one copy of the C runtime library in a process is generally very unhealthy. And highly likely to generate heap corruption. If you can't locate it from the stack trace (be sure to change the Debugger Type from Auto to Mixed, always post the stack trace in an SO question) then the next thing you should strongly consider is rebuilding those libraries with the VS version you use.

Can I assume sizeof(GUID)==16 at all times?

The definition of GUID in the windows header's is like this:
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
However, no packing is not defined. Since the alignment of structure members is dependent on the compiler implementation one could think this structure could be longer than 16 bytes in size.
If i can assume it is always 16 bytes - my code using GUIDs is more efficient and simple.
However, it would be completely unsafe - if a compiler adds some padding in between of the members for some reason.
My questions do potential reasons exist ? Or is the probability of the scenario that sizeof(GUID)!=16 actually really 0.
It's not official documentation, but perhaps this article can ease some of your fears. I think there was another one on a similar topic, but I cannot find it now.
What I want to say is that Windows structures do have a packing specifier, but it's a global setting which is somewhere inside the header files. It's a #pragma or something. And it is mandatory, because otherwise programs compiled by different compilers couldn't interact with each other - or even with Windows itself.
It's not zero, it depends on your system. If the alignment is word (4-bytes) based, you'll have padding between the shorts, and the size will be more than 16.
If you want to be sure that it's 16 - manually disable the padding, otherwise use sizeof, and don't assume the value.
If I feel I need to make an assumption like this, I'll put a 'compile time assertion' in the code. That way, the compiler will let me know if and when I'm wrong.
If you have or are willing to use Boost, there's a BOOST_STATIC_ASSERT macro that does this.
For my own purposes, I've cobbled together my own (that works in C or C++ with MSVC, GCC and an embedded compiler or two) that uses techniques similar to those described in this article:
http://www.pixelbeat.org/programming/gcc/static_assert.html
The real tricks to getting the compile time assertion to work cleanly is dealing with the fact that some compilers don't like declarations mixed with code (MSVC in C mode), and that the techniques often generate warnings that you'd rather not have clogging up an otherwise working build. Coming up with techniques that avoid the warnings is sometimes a challenge.
Yes, on any Windows compiler. Otherwise IsEqualGUID would not work: it compares only the first 16 bytes. Similarly, any other WinAPI function that takes a GUID* just checks the first 16 bytes.
Note that you must not assume generic C or C++ rules for windows.h. For instance, a byte is always 8 bits on Windows, even though ISO C allows 9 bits.
Anytime you write code dependent on the size of someone else's structure,
warning bells should go off.
Could you give an example of some of the simplified code you want to use?
Most people would just use sizeof(GUID) if the size of the structure was needed.
With that said -- I can't see the size of GUID ever changing.
#include <stdio.h>
#include <rpc.h>
int main () {
GUID myGUID;
printf("size of GUID is %d\n", sizeof(myGUID));
return 0;
}
Got 16. This is useful to know if you need to manually allocate on the heap.

Resources