Strange Klocwork issues reported for C++ project - c++

I am finding some of the issues reported by Klocwork is very strange. For example -
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
Time_Critical_Section cs(*m_pMutex);
For the above code Klocwork reports NULL pointer dereference. But I don't think this is a valid issue. As if the pointer is null it would have returned from the function and wouldn't have a chance to access the pointer. But stil Klocwork reported this as an issue.
Another issue is-
char buf[1000];
sprintf(buf,"%s",name);
for the above code Klocwork says the above code portion can cause Buffer overflow, array index of 'buf' may be out of bounds. But we are confirming that the name variable will not be greater than 1000 bytes. But still Klocwork reported this as an issue.
We need to make our code error free, and the final code should not contain any issues for Klocwork. Could anyone suggest an efficient way to overcome the above issues?

Found the root cause of null pointer dereference issue. Let us explain why this code is getting null pointer dereference.
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
Time_Critical_Section cs(*m_pMutex);
As Klocwork is a static code analyzer when it comes to check the pointer in "Time_Critical_Section cs(*m_pMutex);" it finds it in open block though it has been checked earlier and if the pointer is null we have returned from the function with value -1. When Klocwork is doing static code analysis it is unknown to it that it has earlier checked the pointer as the accessing code of pointer in open block. We can solve this problem by modifying the code in following way -
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
else
{
Time_Critical_Section cs(*m_pMutex);
//Do some operations
return 0;
}

Related

Why Simply de-referencing a pointer with NULL assigned is not crashing [duplicate]

This question already has answers here:
What happens in OS when we dereference a NULL pointer in C?
(5 answers)
Closed 6 years ago.
#include <iostream>
int main()
{
int *ptr = NULL;
// It does not crash
*ptr; --------> Point-1
//But this statment crashed
std::cout<<"Null:"<<*ptr<<"\n"; ------> Point-2
return 0;
}
In the above code when i comment "Point-2" the code is not crashed.
But when i un-comment the "Point-2" it is crashed.
Since ptr is NULL ideally the Point-1 should also crash. Please corret me if i am wrong.
Can someone explain me why the code not crashed when i simply dereffernece the pointer ?
Dereferencing a null pointer is undefined behavior. Undefined behavior is not equal to error. Anything may happen if you triggered undefined behavior. If you are asking the other way:
Why is undefined behavior not causing an error instead of giving us strange behavior?
It may be due to many reason. One reason is performance. For example, in the implementation of std::vector (at least in MSVC), there is no check if the index is out of range in Release Mode. You can try to do this:
std::vector<int> v(4);
v[4]=0;
It will compile and run. You may got strange behavior or you may not. However, in Debug mode it will throw exception at run-time. MSVC does the check in Debug Mode because performance is not important in Debug Mode. But it does not in Release Mode because performance matters.
The same applies for dereferencing a null pointer. You can image that the code of dereferencing will be put in a wrapper like this:
//Imaginary code
T& dereference(T* ptr){
if(ptr==nullptr){
throw;
}
return *ptr;
}
This part: if(ptr==nullptr){throw;} will slow the dereferencing process of every pointer in the context which is not desirable.
However, it may be done like this:
//Imaginary code
T& dereference(T* ptr){
#ifdef DEBUG
if(ptr==nullptr){
throw;
}
#endif
return *ptr;
}
I think you got the idea now.
In point 2 you try to display contents of 0x0 address, which generates access violation error.
In point 1, you do nothing with it, so the program doesn't have to access memory described by this pointer. This generates no acces violation error.

c++ check variable to address out of bounds

I use some function, and this function return variable of LPWSTR type (wchar_t*)
at debugger i look at this variable and see error "0x2e (Address 0x2e out of bounds)"
and when i do some operations with its variable, my program terminated.
I can't change called function, i haven't its src code.
my question is : Is c/c++ language have functions to check situation before call incorrect variable? i try try/catch block, but its not helped.
Excuse me for my english and thanks for any help
edited:
fragment of code with error
PCERT_EXTENSION pCe = CertFindExtension(szOID_CRL_DIST_POINTS, pCertInfo->cExtension, pCertInfo->rgExtension);
if (pCe) {
PCRL_DIST_POINTS_INFO pCrlDistPointsInfo = NULL;
PCRL_DIST_POINT *pCrlDistPointsPtr = NULL;
PCRL_DIST_POINT pCrlDistPoints = NULL;
DWORD pdwCrlDistPoints = sizeof (CRL_DIST_POINTS_INFO);
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_CRL_DIST_POINTS,
pCe->Value.pbData,
pCe->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
(PCRYPT_DECODE_PARA) NULL,
&pCrlDistPointsInfo,
&pdwCrlDistPoints)) {
printf("\n\nCannot decode CRL URL.\n\n");
}
if (pCrlDistPointsInfo) {
pCrlDistPointsPtr = (PCRL_DIST_POINT*) pCrlDistPointsInfo->rgDistPoint;
if (pCrlDistPointsPtr && pCrlDistPointsInfo->cDistPoint > 0) {
findCDP = true;
fwprintf(pFile, L"^^");
for (int i = 0; i < pCrlDistPointsInfo->cDistPoint; i++) {
pCrlDistPoints = &pCrlDistPointsInfo->rgDistPoint[i];
if (pCrlDistPoints) {
LPWSTR str = (LPWSTR) pCrlDistPoints->DistPointName._empty_union_.FullName.rgAltEntry->_empty_union_.pwszURL;
//printf("last error= 0x%08X", GetLastError());
fwprintf(pFile, str);//PROGRAM TERMINATED HERE!!!
fwprintf(pFile, L";");
}
printf("%d\n",i);
}
}
free(pCrlDistPointsInfo);
}
}
No, it doesn't have. If you set a pointer, which points to an invalid memory location, every access to the object at that location is an undefined behavior. What will most likely happen is a crash or some kind of memory corruption.
If a pointer has value 0x0000002e, it can mean only two things:
A bug in code which returns that. You're out of luck if you can't fix that...
An undefined pointer value, and reason for error is returned some other way, such as by modified reference parameter. But returning undefined value instead of null pointer would still count as a bug in my book.
On the other hand 0x2e sounds like ASCII character, '.' to be exact, so are you sure you are looking at pointer value instead of the string pointed to?
Late edit: looking at the code, it seems unions are involved. A possible reason for crash then is, you are accessing wrong member of union. In C union, all members/fields are in same memory location, they overlap. In other words, union can hold only one value at a time, and you need to know which one somehow, such as from documentation of function which initializes the union value, or by some extra variable which tells the type (common pattern in C is to have struct which contains type field and union field).
Windows has functions to check whether an address is a correct address or not. BUT... it's bad practice to rely on this, since there is no guarantee that if the pointer points to a correct address, that this is the address that you want.
The functions in windows are: IsBadReadPtr, IsBadWritePtr and IsBadCodePtr. I strongly suggest to only use these functions in debugging code (asserts e.g.) and never rely on this in a release executable.
If your application is designed and working correctly, you should never rely on these Windows functions.

Access Violation on char array

I'm getting an access violation on a char array I just created using new.
DispatchCommand(char* cmdStr)
{
// Dispatch
for(int i = 0; i < sizeof(_lpCommands); i++)
{
const int len = strlen(_lpCommands[i].szCommand);
char* cmdblip = new char[len + 1];
memcpy(&cmdblip, cmdStr, len);
cmdblip[len] = '\0'; // Access Violation
if(strcmp(cmdblip, _lpCommands[i].szCommand) == 0)
{
if(strlen(cmdStr) > strlen(_lpCommands[i].szCommand))
(*_lpCommands[i].cbCallback)(&cmdStr[strlen(_lpCommands[i].szCommand)]);
else
(*_lpCommands[i].cbCallback)("");
delete cmdblip;
return;
}
delete cmdblip;
}
// Error and return
*Out::ServerInfo<<"Command not found!"<<ENDL;
}
_lpCommands is an array of Command structures:
struct Command
{
char* szCommand;
CommandCallback cbCallback;
};
The produced error message is:
Unhandled exception at 0x012219cf in Program.exe: 0xC0000005: Access
violation writing location 0x66647366.
This was a rewrite of similar code which was using memcmp, which ended up giving me an access violation as well without be doing a memcpy.
What gives?
Don't pass &cmdblip to memcpy. You should pass a pointer to the destination buffer, not a pointer to that pointer. Pass cmdblip instead.
Edit: I agree that in general, std::string should be used in C++. Still, the technical reason this code crashes is that memcpy corrupts the cmdblip pointer, making it point on a memory location that is actually made of the first 4 bytes of the copied string. Then, cmdblip[len] results in a memory location that is not within the allocated buffer (or any other legally allocated buffer), hence the crash. So, if you want to write better code, use C++ classes. And if you want to understand why the given code crashed, consider the above.
The only possible helpful answer to this question is "Use std::string". The specific problem you are having now will simply re-occur, or an identical one, every time you modify this function or write another like it. The only way to solve the problem in the general case is to move to a class-based solution, which is kindly provided for you as Standard. For example, your current code is exception unsafe, on top of whatever is giving you an access violation, not to mention that it's unreadable and begging for a number of other errors, such as off-by-one, not properly NULL terminating, double deletes, and memory leaks. Oh, and UB because you delete what you new[].

Error - There is no source code available for the current location

When I'm trying to debug a C program written on Linux machine (right now, I'm using Visual C++ Express), I first get a stack overflow error. So when I clicked continue, I got another error message,
Access violation reading location 0x00030000
So I decide to debug step by step. So when I try it, it shows me the error
There is no source code available for the current location.
What is the reason for this error?
The Code
#if 1
while(1)
#endif
{
fillList();
#if 1
{
op_ds_bulk(ops, &total, 1);
temp = res("Bulk Write:", total, fp);
index = 0;
}
#endif
void op_ds_bulk(u_int ops, u_int * totalp, int update)
{
char encode_db[] = "encode";
if(update)
{
database_insert_bluk(list, ops);
database_sync();
*totalp = ops;
}
else
{
CHUNK prefetch[4096];
int random = rand() % (h-ops+1);
__os_clock(NULL, &start_time.secs, &start_time.usecs);
database_select_end(65546, random, prefetch, ops);
__os_clock(NULL, &end_time.secs, &end_time.usecs);
*totalp = ops;
}
}
}
The invalid access might occur somewhere in the standard library code. The source for that is not available in the Express edition.
You might check the call stack for the part of your code that calls a library function, and work it from there.
Some time ago I had a similar problem, maybe it is related to yours?
I had an array on the stack (you have one too - prefetch) and I accidently cleared it too far (out of bounds of the array), removing whatever information was beyond the array.
When you call a function, the return address is also stored on the stack (computer must know where to return from a function). Since I have cleared that, the program jumped under address 0x0 and SegFault-ed. When debugging, I also got a message "there is no source code at current location", because "current location" was 0x0 and of course there was no code there.
So I suspect that you go out-of-bounds on some array which is on the stack.
By looking at your code, I see two suspicious things:
The size of your prefetch array is 4096, but you call database_select_end with parameter 65546. Maybe it is ok (no idea what that function does) but maybe it is not ;)
65546 is not a power of 2. 2^16=65536
I solved the problem by writing the same code with a different function name. It's so weird for me because it solved my problem. I don't know why.

Why check only certain values for errors? (C++?)

I recently started learning DirectX/Windows, and the book I'm learning from had the code
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL)
//catch error &c.
My question is: What would cause an error in this line, that is different than what would cause an error in another line (say, for example, int num = 42)?
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
This is an error or not according to the meaning you give to the return value of Direct3DCreate9, i.e. depending on the specification of the function. I've written many pointer-returning functions for which NULL as a return value was not an erroneous situation.
So, do not equate "a function returning NULL" to "an error". An unambiguous error is a crash (technically, undefined behaviour) in your code, like if d3d is indeed NULL and later you dereference it.
int num = 42;
Here you are declaring an int variable called num and initializing it with a value of 42. What kind of error can you think of? Obviously, num will never "be NULL", if that bothers you. 42 may be a correct value or an error, depending on the context.
I think the comment is indicating that if Direct3DCreate9(D3D_SDK_VERSION); has returned NULL, then it is an error that should be handled.
From msdn:
IDirect3D9 * Direct3DCreate9( UINT
SDKVersion );
Parameters
SDKVersion
The value of this parameter should be D3D_SDK_VERSION. See Remarks.
Return Values
If successful, this function returns a
pointer to an IDirect3D9 interface;
otherwise, a NULL pointer is returned.
It is not saying that the comparison d3d == NULL might throw an exception.
It's important to catch that error because it's a show-stopper and because it can and does happen. As for other errors - I don't know what other errors you're talking about.
Certainly all errors should be checked for and handled. But remember that in a book, the priority is to make the key points as readable and understandable as possible. Complete error checking would get in the way of that, so it is often left as that infamous exercise for the reader.