I am using C Style strings for a project, and I am confusing myself a bit. I am checking strings to see what they are prepended with (zone_, player_, etc) then getting the rest of the string after that.
else if(strncmp(info, "zone_", 5) == 0)
{
int len = strlen(info);
char *zoneName = new char[len];
strncpy(zoneName, &info[5], len-5);
Msg("Zone Selected: %s\n", zoneName);
delete zoneName;
}
When I print out the zoneName variable though, it is correct except it is followed by a bunch of gibberish. What am I doing wrong? (I realize that the gibberish is the rest of the char array being empty, but I don't know a better way to do this)
See strncpy description :
No null-character is implicitly
appended to the end of destination, so
destination will only be
null-terminated if the length of the C
string in source is less than num.
You have to remember that C-style strings are terminated with a NUL character. You've allocated enough space in zoneName, but you only need len-5 plus one:
char *zoneName = new char[len - 5 + 1];
Then, you can actually use strcpy() to copy the tail of the string:
strcpy(zoneName, &info[5]);
You don't need to specify the length because the source string is NUL terminated.
C strings are zero terminated - so they occupy len bytes (chars to be precise) plus one more with value zero known as the 'zero terminator'. You need to allocate one more character, and either copy one more from the source (since it should be zero terminated) or just set the last char of the destination to 0.
int len = strlen(info);
char *zoneName = new char[len - 5 + 1];
strncpy(zoneName, &info[5], len - 5 + 1);
C-style strings has to be finished with a byte with zero value. You should modify your code like this:
char *zoneName = new char[len-5+1];
strncpy(zoneName, &info[5], len-5);
/* correct string ending */
zoneName[len]=0;
/* Now, it's safe to print */
Msg("Zone Selected: %s\n", zoneName);
Related
Why does this code produce runtime issues:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
but this doesn't?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat will look for the null-terminator, interpret that as the end of the string, and append the new text there, overwriting the null-terminator in the process, and writing a new null-terminator at the end of the concatenation.
char stuff[100]; // 'stuff' is uninitialized
Where is the null terminator? stuff is uninitialized, so it might start with NUL, or it might not have NUL anywhere within it.
In C++, you can do this:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
Now you can do strcat, because the first character of 'stuff' is the null-terminator, so it will append to the right place.
In C, you still need to initialize 'stuff', which can be done a couple of ways:
char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
// so 'stuff' is effectively ""
strcpy(stuff, "hi "); // this initializes 'stuff' if it's not already.
In the first case, stuff contains garbage. strcat requires both the destination and the source to contain proper null-terminated strings.
strcat(stuff, "hi ");
will scan stuff for a terminating '\0' character, where it will start copying "hi ". If it doesn't find it, it will run off the end of the array, and arbitrarily bad things can happen (i.e., the behavior is undefined).
One way to avoid the problem is like this:
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
Or you can initialize stuff to an empty string:
char stuff[100] = "";
which will fill all 100 bytes of stuff with zeros (the increased clarity is probably worth any minor performance issue).
Because stuff is uninitialized before the call to strcpy. After the declaration stuff isn't an empty string, it is uninitialized data.
strcat appends data to the end of a string - that is it finds the null terminator in the string and adds characters after that. An uninitialized string isn't gauranteed to have a null terminator so strcat is likely to crash.
If there were to intialize stuff as below you could perform the strcat's:
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");
Strcat append a string to existing string. If the string array is empty, it is not going go find end of string ('\0') and it will cause run time error.
According to Linux man page, simple strcat is implemented this way:
char*
strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
As you can see in this implementation, strlen(dest) will not return correct string length unless dest is initialized to correct c string values. You may get lucky to have an array with the first value of zero at char stuff[100]; , but you should not rely on it.
Also, I would advise against using strcpy or strcat as they can lead to some unintended problems.
Use strncpy and strncat, as they help prevent buffer overflows.
I am trying to read 4 characters at a specific position from a file. The code is simple but the result is really confusing:
fstream dicomFile;
dicomFile.open(argv[1]);
dicomFile.seekg(128,ios::beg);
char * memblock = new char [4];
dicomFile.read(memblock,4);
cout<<"header is "<<memblock<<endl;
Ideally the result should be "DICM" but the actual result from the console was "DICM" plus weird characters, as shown in the picture. What's more, every time I run it, the characters are different. I suppose this may be something about ASCII and Unicode, I tried to change project property from Unicode to multibytes and then change back, no difference.
Does anyone know what's happening here and how do I solve it please? Thanks very much!
C style (char *) strings use the concept of null-terminators. This means strings are ended with a '\0' character in their last element. You are reading in exactly 4 characters into a 4 character buffer, which does not include a null character to end the string. C and C++ will happily run right off the end of your buffer in search for the null terminator that signifies the end of the string.
Quick fix is to create a block of length + 1, read in length data, then set str[length] = '\0'. In your case it would be as below.
char * memBlock = new char [5];
// populate memBlock with 4 characters
memBlock[ 4 ] = '\0';
A better solution is to use std::string instead of char * when working with strings in C++.
You could also initialize the buffer with zeros, putting null-terminators at every location.
char * memblock = new char [5](); // zeros, and one element longer
Fairly inefficient though.
I wrote a dll application that is hooked into a process. It works but it ONLY shows the FIRST letter.
I wanted to get the whole string. The string could vary from 2 letters to 32 letters.
//READING MEMORY
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%c \n", uNameAddr);
I also wanted to understand the parts:
*(char*)((char*) //<-- what this is for.
And if it is possible to use this if using multilevel pointers:
char multipoint = *(char*)((char*)ExeBaseAddress + 0x34F01C + 0x123 + 0x321 + 0x20);
UPDATE
I guess something is wrong here:
if(uNameAddr == "omnicient")
cout << "YOU ARE OMNI" << endl;
I used the username name omnicient but it did not cout YOU ARE OMNI. I guess my compare is wrong?
%c displays chars (single characters), %s displays NULL-terminated char*s (strings):
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char *uNameAddr = (char*) ExeBaseAddress + 0x34F01C;
printf("%s \n", uNameAddr);
Notice that I also tidied up the pointer casting, but the important thing is I got rid of the final dereference (* at the front) and assigned it to a char* (pointer) instead of a char.
If your string isn't NULL-terminated (unlikely), you will need to use %.*s and pass the length of your string too.
As for the second part of your question:
*(char*)((char*) ExeBaseAddress + 0x34F01C)
let's break it down. Inside the brackets (therefore the first thing to be evaluated) is this:
(char *) ExeBaseAddress + 0x34F01C
Well that's a C cast (casting the HANDLE to a char*) followed by an addition. In other words, it says "Treat this thing as if it is a pointer to some memory, then look ahead by 0x34F01C bytes of memory" (char is always 1 byte). It is now a pointer to a new position in memory.
Then we get out of the brackets and cast to char* again... needlessly. It could have been:
*((char*) ExeBaseAddress + 0x34F01C)
and finally we dereference (the * at the front), which says "Now tell me what the bit of memory you're pointing to is". But in this case you don't want that, because you want the whole string, not just the first letter (inside printf, it loops along the memory you send it printing each character until it finds a 0, aka \0 aka NULL).
char uNameAddr is a character, you need a list of chars (or char*)
try this instead:
char* name= (char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%s \n", name);
What does *(char*)((char*) mean?
(char*)ExeBaseAddress treat ExeBaseAddress as a pointer to some data of type char
((char*)ExeBaseAddress + 0x34F01C) means add 0x34F01C to the above pointer to offset it by 0x34F01C chars
(char*)((char*)ExeBaseAddress + 0x34F01C) means treat this new address as pointer to some chars
*(char*)((char*)ExeBaseAddress + 0x34F01C) take the contents of the first char at that location
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C); means put that character into the char sized variable called uNameAddr.
So basically you had a pointer, you offset it, and then took the first character and printed it.
In the example I gave note how I don't take the firat character, and I put it a pointer variable.
Then I used %s in the printf to make it print out all the chars potnted to by name.
I'm just started to pick up C and I am working on using the RSA cipher in my code. However, this line of code confuses me. Credits go to the author from this site here.
char* intmsg = new char[strlen(msg)*3 + 1];
This is the method which the line can be found.
inline void encrypt(char* msg,FILE* fout)
{
/* This function actually does the encrypting of each message */
unsigned int i;
int tmp;
char tmps[4];
char* intmsg = new char[strlen(msg)*3 + 1];
/* Here, (mpz_t) M is the messsage in gmp integer
* and (mpz_t) c is the cipher in gmp integer */
char ciphertext[1000];
strcpy(intmsg,"");
for(i=0;i<strlen(msg);i++)
{
tmp = (int)msg[i];
/* print it in a 3 character wide format */
sprintf(tmps,"%03d",tmp);
strcat(intmsg,tmps);
}
mpz_set_str(M,intmsg,10);
/* free memory claimed by intmsg */
delete [] intmsg;
/* c = M^e(mod n) */
mpz_powm(c,M,e,n);
/* get the string representation of the cipher */
mpz_get_str(ciphertext,10,c);
/* write the ciphertext to the output file */
fprintf(fout,"%s\n",ciphertext);
}
That code line isn't actually C, it's C++.
char* intmsg = new char[strlen(msg)*3 + 1];
Means to dynamically allocate a block of memory with room for the given number of chars, 3 times bigger + 1 than the original length of the msg string.
The C equivialent would be
char* intmsg = malloc(strlen(msg)*3 + 1);
To deallocate that memory block, delete []intmsg is used in C++, while if you used malloc in C, you'd do free(intmsg);
It creates an array of character which is 3 times larger than the list of characters stored in msg plus one character to store the string ending character '\0'.
More info on the C++ operator new[] here
Its a line of C++, and its dynamically allocating an array of chars 3 times the length of string "msg" + 1 more (for the null terminator)
This is C++ and the code allocates an array of char, the size of which is 3 times the length of the messages, plus one. The resulting pointer is assigned to intmsg.
Why does it do that? Because the message is converted, character by character, to a three digit per character decimal number in the loop with the sprintf(tmps,"%03d",tmp);.
It's c++ code :
char* intmsg = new char[strlen(msg)*3 + 1];
This tells the compiler to create memory for intmsg on heap of length of memory block ie equal to "one more than the 3 times of length of the msg".
means After the execution of this line intmsg started pointing to the block of memory on heap.
I wrote a very simple encryption program to practice c++ and i came across this weird behavior. When i convert my char* array to a string by setting the string equal to the array, then i get a wrong string, however when i create an empty string and add append the chars in the array individually, it creates the correct string. Could someone please explain why this is happening, i just started programming in c++ last week and i cannot figure out why this is not working.
Btw i checked online and these are apparently both valid ways of converting a char array to a string.
void expandPassword(string* pass)
{
int pHash = hashCode(pass);
int pLen = pass->size();
char* expPass = new char[264];
for (int i = 0; i < 264; i++)
{
expPass[i] = (*pass)[i % pLen] * (char) rand();
}
string str;
for (int i = 0; i < 264; i++)
{
str += expPass[i];// This creates the string version correctly
}
string str2 = expPass;// This creates much shorter string
cout <<str<<"\n--------------\n"<<str2<<"\n---------------\n";
delete[] expPass;
}
EDIT: I removed all of the zeros from the array and it did not change anything
When copying from char* to std::string, the assignment operator stops when it reaches the first NULL character. This points to a problem with your "encryption" which is causing embedded NULL characters.
This is one of the main reasons why encoding is used with encrypted data. After encryption, the resulting data should be encoded using Hex/base16 or base64 algorithms.
a c-string as what you are constructing is a series of characters ending with a \0 (zero) ascii value.
in the case of
expPass[i] = (*pass)[i % pLen] * (char) rand();
you may be inserting \0 into the array if the expression evaluates to 0, as well as you do not append a \0 at the end of the string either to assure it being a valid c-string.
when you do
string str2 = expPass;
it can very well be that the string gets shorter since it gets truncated when it finds a \0 somewhere in the string.
This is because str2 = expPass interprets expPass as a C-style string, meaning that a zero-valued ("null") byte '\0' indicates the end of the string. So, for example, this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s = p;
will cause s to have length 1, since p has only one nonzero byte before its terminating '\0'. But this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s;
s += p[0];
s += p[1];
will cause s to have length 2, because it explicitly adds both bytes to s. (A std::string, unlike a C-style string, can contain actual null bytes — though it's not always a good idea to take advantage of that.)
I guess the following line cuts your string:
expPass[i] = (*pass)[i % pLen] * (char) rand();
If rand() returns 0 you get a string terminator at position i.