Exception when using strncpy - c++

The following code fragment ends in an exception when executing the strncpy function:
#define MAX_FILENAME_LEN 127
typedef struct {
unsigned long nameLength;
char name[MAX_FILENAME_LEN + 1];
} filestructure;
char *fileName;
strncpy( fileName, filestructure->name, MAX_FILENAME_LEN );
*( fileName + MAX_FILENAME_LEN+1 ) = 0;
Ayone an idea what could go wrong? In the filestructure I have a filename that is 50 characters long so it is within the bounds... I am really a bit lost what could cause the problem in this simple code fragement...

You haven't allocated space for the destination buffer and fileName is uninitialized. So you try to copy somewhere. You should allocate memory and then bother freeing it.
char *fileName = new char[MAX_FILENAME_LEN + 1];
strncpy(...);
*(...) = 0;
doStuffWithTheBuffer( fileName );
delete[] fileName;// free memory
Also if you have a buffer of size N + 1 and want to copy N bytes maximum and null-terminate the buffer you should do
*(buffer + N) = 0;

Your question is tagged C++ but the code is pure C. Why do you do it the hard way? The fact that C string handling isn't all that easy to grasp (and that it isn't all that uncommon to get something wrong once in a while even for programmers who have a good grasp of it) is the very reason C++ let's you do without.
If you're writing C++, do it the C++ way. Use std::string. Honestly, it will spare you many hours of debugging such code.

You haven't allocated space for filename. Either do
filename = malloc (MAX_FILENAME_LEN * sizeof(char));
or
filename = strndup (filestructure->name, MAX_FILENAME_LEN);

Related

Memory corruption on multiple 'strcat' with same src

This is a very easy problem but im stunned that i cant find a easy solution.
I am tring to create two strings that are path to files.
/Metadata/bitmap
/Metadata/Metadata.bin
but the second time i try to do the strcat() with the same src variable explodes into memory corruption
//create the dir strign to append
char* metadata_dir = strdup(MNT_POINT);
strcat(metadata_dir, "Metadata/");
char* bitmap_file = strdup("");
strcat(bitmap_file,metadata_dir);
strcat(bitmap_file,"bitmap");
printf("%s\n",bitmap_file);
char* meta_file = strdup("");
strcat(meta_file, metadata_dir);
strcat(meta_file, "Metadata.bin");
printf("%s\n",meta_file);
rigth in the line
strcat(meta_file, metadata_dir);
the memory corruption happens.
I am shure that metadata_dir is not corrupted because i can print it anywhere in the code and it looks fine.
The weird thing is that this happens depenend on the machine that is running on. In Ubuntu 64 works just fine. But in the 32bits version no.
strdup is only guaranteed to return a buffer big enough for the string you're duplicating (null terminator included); it may not (and often will not) have room for concatenating other things to it. You're overwriting random memory when you write past the end of the string with strcat.
EDIT: the solution, of course, is to malloc a buffer large enough in advance, instead of letting strdup do that.
Code fails as metadata_dir is only certainly big enough for MNT_POINT, not MNT_POINT and "Metadata/"
char* metadata_dir = strdup(MNT_POINT);
strcat(metadata_dir, "Metadata/");
To allocate and concatenate:
char *allocate_cat(const char *s1, const char *s2) {
size_t len1 = strlen(s1);
size_t size2 = strlen(s2) + 1;
char *s12 = malloc(len1 + size2); // allocate enough room for both
if (s12) {
memcpy(s12, s1, len1);
memcpy(s12 + s1, s2, size2);
}
return s12;
}

String is not null terminated error

I'm having a string is not null terminated error, though I'm not entirely sure why. The usage of std::string in the second part of the code is one of my attempt to fix this problem, although it still doesn't work.
My initial codes was just using the buffer and copy everything into client_id[]. The error than occurred. If the error is correct, that means I've got either client_ id OR theBuffer does not have a null terminator. I'm pretty sure client_id is fine, since I can see it in debug mode. Strange thing is buffer also has a null terminator. No idea what is wrong.
char * next_token1 = NULL;
char * theWholeMessage = &(inStream[3]);
theTarget = strtok_s(theWholeMessage, " ",&next_token1);
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
Inside sendTalkPackets is. I'm getting a string is not null terminated at the last line.
void ServerGame::sendTalkPackets(char * buffer, unsigned int buffersize, unsigned int theSender, unsigned int theReceiver)
{
std::string theMessage(buffer);
theMessage += "0";
const unsigned int packet_size = sizeof(Packet);
char packet_data[packet_size];
Packet packet;
packet.packet_type = TALK;
char client_id[MAX_MESSAGE_SIZE];
char theBuffer[MAX_MESSAGE_SIZE];
strcpy_s(theBuffer, theMessage.c_str());
//Quick hot fix for error "string not null terminated"
const char * test = theMessage.c_str();
sprintf_s(client_id, "User %s whispered: ", Usernames.find(theSender)->second.c_str());
printf("This is it %s ", buffer);
strcat_s(client_id, buffersize , theBuffer);
Methinks that problem lies in this line:
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
sizeof(next_token1)+1 will always gives 5 (on 32 bit platform) because it return size of pointer not size of char array.
One thing which could be causing this (or other problems): As
buffersize, you pass sizeof(next_token1) + 1. next_token1 is
a pointer, which will have a constant size of (typically) 4 or 8. You
almost certainly want strlen(next_token1) + 1. (Or maybe without the
+ 1; conventions for passing sizes like this generally only include
the '\0' if it is an output buffer. There are a couple of other
places where you're using sizeof, which may have similar problems.
But it would probably be better to redo the whole logic to use
std::string everywhere, rather than all of these C routines. No
worries about buffer sizes and '\0' terminators. (For protocol
buffers, I've also found std::vector<char> or std::vector<unsigned char>
quite useful. This was before the memory in std::string was
guaranteed to be contiguous, but even today, it seems to correspond more
closely to the abstraction I'm dealing with.)
You can't just do
std::string theMessage(buffer);
theMessage += "0";
This fails on two fronts:
The std::string constructor doesn't know where buffer ends, if buffer is not 0-terminated. So theMessage will potentially be garbage and include random stuff until some zero byte was found in the memory beyond the buffer.
Appending string "0" to theMessage doesn't help. What you want is to put a zero byte somewhere, not value 0x30 (which is the ascii code for displaying a zero).
The right way to approach this, is to poke a literal zero byte buffersize slots beyond the start of the buffer. You can't do that in buffer itself, because buffer may not be large enough to accomodate that extra zero byte. A possibility is:
char *newbuffer = malloc(buffersize + 1);
strncpy(newbuffer, buffer, buffersize);
newbuffer[buffersize] = 0; // literal zero value
Or you can construct a std::string, whichever you prefer.

Stack around the variable 'dim'(not an array) was corrupted

I'm trying to read from a binary file, using fstream, some data I have previously written there.
The problem is that after getting to the end of the function the message in the subject is shown
The code is the following:
ifstream in("contrib.bin", ios::in | ios::binary );
char *nume, dim;
in.read((char*)&dim, sizeof(int));
nume = new char[dim + 1];
in.read(nume, dim);
nume[dim] = '\0';
double imp;
in.read((char*)&imp, sizeof(double));
delete [] nume;
Now, I've done my homework and looked for this issue, but the other people who faced it had arrays, whereas my variable is a simple char.
Can someone point me to the right direction, please?
The code
char dim;
in.read((char*)&dim, sizeof(int));
defines a 1 byte char then reads sizeof(int) bytes (which is likely to be greater that 1) into it. This is invalid and may corrupt your stack.
If you need to read sizeof(int) bytes, declare dim as int. Otherwise, change the number of bytes you read to 1. It'd be best if you also used sizeof(dim) to ensure that you only read as many bytes as you've provided storage for:
in.read((char*)&dim, sizeof(dim));
in.read((char*)&dim, sizeof(int)); is not correct, dim only holds sizeof(char) which is one, but you're attempting to read sizeof(int) into it.
All gloves are off after this.
Well you define a character then read in the size of an int. That would be the first issue
char *nume, dim;
in.read((char*)&dim, sizeof(char));

C++ TCP socket garbage value

I have my socket comms pretty much working. The only thing that I'm not sure about is why I'm getting some garbage values at the end of my message. The first message I send contains some extra characters at the end, and every message after that is as expected...does anyone have any insight as to why this is happening?
Send:
CString string = "TEST STRING TO SEND";
char* szDest;
szDest = new char[string.GetLength()];
strcpy(szDest,string);
m_pClientSocket->Send(szDest,strlen(pMsg));
Receive: (this is using Qt)
char* temp;
int size = tcpSocket->bytesAvailable();
temp = new char[size];
tcpSocket->read(temp,size);
You will be missing the \0 in your temp after read, since it's not really transmitted (and probably shouldn't be)
You likely need to change the receive a little bit:
temp = new char[size + 1];
int realSize = tcpSocket->read(temp, size);
temp[realSize] = 0;
Btw, you would be better off with QTcpSocket::readAll() in this little snipped.
I don't know this CString class, but I see two bugs here:
Does GetLength() include the terminating NUL? If not, your char buffer is one byte smaller than it needs to be, and the strcpy is clobbering memory after the end of the buffer.
strlen(pMsg) is the length of something other than szDest. This is probably the immediate cause of your problem.
The char buffer appears to be unnecessary: why don't you just do
CString string = "TEST STRING TO SEND";
m_pClientSocket->Send(string, string.GetLength());
?

Please suggest what is wrong with this string reversal function?

This code is compiling clean. But when I run this, it gives exception "Access violation writing location" at line 9.
void reverse(char *word)
{
int len = strlen(word);
len = len-1;
char * temp= word;
int i =0;
while (len >=0)
{
word[i] = temp[len]; //line9
++i;--len;
}
word[i] = '\0';
}
Have you stepped through this code in a debugger?
If not, what happens when i (increasing from 0) passes len (decreasing towards 0)?
Note that your two pointers word and temp have the same value - they are pointing to the same string.
Be careful: not all strings in a C++ program are writable. Even if your code is good it can still crash when someone calls it with a string literal.
When len gets to 0, you access the location before the start of the string (temp[0-1]).
Try this:
void reverse(char *word)
{
size_t len = strlen(word);
size_t i;
for (i = 0; i < len / 2; i++)
{
char temp = word[i];
word[i] = word[len - i - 1];
word[len - i - 1] = temp;
}
}
The function looks like it would not crash, but it won't work correctly and it will read from word[-1], which is not likely to cause a crash, but it is a problem. Your crashing problem is probably that you passed in a string literal that the compiler had put into a read-only data segment.
Something like this would crash on many operating systems.
char * word = "test";
reverse(word); // this will crash if "test" isn't in writable memory
There are also several problems with your algorithm. You have len = len-1 and later temp[len-1] which means that the last character will never be read, and when len==0, you will be reading from the first character before the word. Also, temp and word are both pointers, so they both point to the same memory, I think you meant to make a copy of word rather than just a copy of the pointer to word. You can make a copy of word with strdup. If you do that, and fix your off-by-one problem with len, then your function should work,
But that still won't fix the write crash, which is caused by code that you have not shown us.
Oh, and if you do use strdup be sure to call free to free temp before you leave the function.
Well, for one, when len == 0 len-1 will be a negative number. And that's pretty illegal. Second, it's quite possible that your pointer is pointing at an unreserved area of memory.
If you called that function as followed:
reverse("this is a test");
then with at least one compiler will pass in a read only string due to backwards compatibility with C where you can
pass string literals as non-const char*.