I’ve allocated a chuck of memory with char* memoryChunk = malloc ( 80* sizeof(char) + 1); What is keeping me from writing into the memory location beyond 81 units? What can I do to prevent that?
void testStage2(void) {
char c_str1[20] = "hello";
char* ut_str1;
char* ut_str2;
printf("Starting stage 2 tests\n");
strcat(c_str1, " world");
printf("%s\n", c_str1); // nothing exciting, prints "hello world"
ut_str1 = utstrdup("hello ");
ut_str1 = utstrrealloc(ut_str1, 20);
utstrcat(ut_str1, c_str1);
printf("%s\n", ut_str1); // slightly more exciting, prints "hello hello world"
utstrcat(ut_str1, " world");
printf("%s\n", ut_str1); // exciting, should print "hello hello world wo", 'cause there's not enough room for the second world
}
char* utstrcat(char* s, char* suffix){
int i = strlen(s),j;
int capacity = *(s - sizeof(unsigned) - sizeof(int));
for ( j =0; suffix[j] != '\0'; j++){
if ((i+j-1) == 20)
return s;
s[i+j] = suffix[j];
}
//strcpy(s, suffix);
s[i + j] = '\0';
return s;
}// append the suffix to s
Nothing. However, doing this results in undefined behaviour. This means anything can happen, and you shouldn’t depend on it doing the same thing twice. 99.999% of the time this is a bug.
Always check that your pointers are within bounds before accessing (reading from or writing to) them. Always make sure strings end with
\0when passing to string functions.You can use debugging tools such as valgrind to assist you in locating bugs related to out-of-bounds pointer and array access.
stdlib’s approach
For your code, you can have
utstrncatwhich acts likeutstrcatbut takes a maximum size (i.e. the size of the buffer).stdc++’s approach
You can also create an array struct/class or use
std::stringin C++. For example:Then have your functions operate on that instead. You can even have dynamic reallocation using this technique (but that doesn’t seem to be what you want).
End-of-buffer marker approach
Another approach is to have an end of buffer marker, similar to the end of string marker. When you encounter the marker, don’t write to that place or one before it (for the end of string marker) (or you can reallocate the buffer so there’s more room).
For example, if you have
"hello world\0xxxxxx\1"as a string (where\0is the end of string marker,\1is the end of buffer marker, and thexare random data). appending" this is fun"would look like the following:Your problem
The problem with your code is here:
Although you are stopping before overrunning the buffer, you are not marking the end of the string.
Instead of returning, you can use
breakto end theforloop prematurely. This will cause the code after theforloop to run. This sets the end of string marker and returns the string, which is what you want.In addition, I fear there may be a bug in your allocation. You have
+ 1to allocate the size before the string, correct? There’s a problem:unsignedis usually not 1 character; you will need+ sizeof(unsigned)for that. I would also writeutget_buffer_sizeandutset_buffer_sizeso you can make changes more easily.