How do I transfer text between different functions in C? - c

I have two .c files that I would like to compile into on executable. Having just started learning C, I'm finding it tricky to know how to transfer text as an argument between functions (which I've found to be incredibly simple in every other language).
Here are the two files:
Program.c
#include <stdio.h>
#include <string.h>
int main(){
char temp[40] = stringCall();
printf("%s",temp);
}
StringReturn.c
#include <stdio.h>
#include <string.h>
char[] stringCall(){
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
}
I usually get a problem that says something like "Segmentation Failed (core dumped)" or alike. I've done a lot of Googling and amazing I can't really find a solution, and certainly no simple tutorial "This is how to move text between functions".
Any help would be appreciated :)

char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
This is invalid, you're returning an auto array which gets out of scope after the function returns - this invokes undefined behavior. Try returning the string literal itself (it's valid throughout the program):
return "Hello, Stack Overflow!";
Or a dynamic duplicate of your array:
char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);
In this latter case, you'll need to free() the string in the caller function.

You are correct, this isn't simple in C because C can't treat strings as values.
The most flexible way to do it is this:
// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
puts(temp);
} else {
// error-handling
puts("My buffer wasn't big enough");
}
// StringReturn.c
int stringCall(char *buf, int size) {
const char toReturn[] = "Hello, Stack Overflow!";
if (sizeof toReturn <= size) {
strcpy(buf, toReturn);
}
return sizeof toReturn;
}
stringCall doesn't return the string data, it writes it to a buffer supplied by the caller
A buffer always comes with a size. You could use size_t or ssize_t for this rather than int.
stringCall checks the size before writing. There are other ways to do this in a single call, all of which are either not in C89 and C99, or are defective in some other way. C11 introduces strcpy_s. Use what tools you can, which should be logically equivalent to checking it yourself as in my code above. Never forget to make sure there's space for the nul terminator, which invisibly lurks at the end of every C string.
stringCall returns the number of bytes that it wants to write, even if it doesn't write anything. This means that a caller whose buffer is too small can allocate a bigger one and try again. For that matter a caller can do stringCall(NULL, 0) to get the size without trying any particular buffer.
I'm using sizeof here because I'm using arrays whose size is known by the compiler, but in practice stringCall might use strlen or some other way of knowing how much data it wants to write.
As I've written it, callers are required not to pass in a negative value for size. That's usually OK, because their buffer in point of fact cannot have a negative size, so their code is already buggy if they do. But if you want to be really sure, or if you want to help your callers catch those bugs, you could write if ((int) sizeof toReturn < size) or if (size > 0 && sizeof toReturn < size).
"Most flexible" isn't always best, but this is good when the function is actually generating the text on the fly, especially when there isn't an easy way for the caller to know the length in advance without doing half the work that stringCall is supposed to do for them. The interface is similar to the C99 standard function snprintf.

Related

How does a program shut down when reading farther than memory allocated to an array?

Good evening everybody, I am learning C++ on Dev C++ 5.9.2, I am really novice at it. I intentionnally make my programs crash to get a better understanding of bugs. I've just learned that we can pass a char string to a function by initializing a pointer with the address of the array and that was the only way to do it. Therefore we should always pass to the function the size of that string to handle it properly. It also means that any procedure can run with a wrong size passed in the argument line hence I supposed we could read farther than the allocated memory assigned to the string.
But how far can we do it? I've tested several integers and apparently it works fine below 300 bytes but it doesn't for above 1000 (the program displays characters but end up to crash). So my questions are :
How far can we read or write on the string out of its memory range?
Is it called an overflow?
How does the program detect that the procedure is doing something unlegit?
Is it, the console or the code behind 'cout', that conditions the shutting down of the program?
What is the condition for the program to stop?
Does the limit depend on the console or the OS?
I hope my questions don't sound too trivial. Thank you for any answer. Good day.
#include <iostream>
using namespace std;
void change(char str[])
{
str[0] = 'C';
}
void display(char str[], int lim)
{
for(int i = 0; i < lim; i++) cout << str[i];
}
int main ()
{
char mystr[] = "Hello.";
change(mystr);
display(mystr, 300);
system("PAUSE");
return 0;
}
The behavior when you read past the end of an array is undefined. The compiler is free to implement the read operation in whatever way works correctly when you don't read beyond the end of the buffer, and then if you do read too far - well, whatever happens is what happens.
So there are no definite answers to most of your questions. The program could crash as soon as you read 1 byte too far, or you could get random data as you read several megabytes and never crash. If you crash, it could be for any number of reasons - though it likely will have something to do with how memory is managed by the OS.
As an aside, the normal way to let a function know where a string ends is to end it with a null character rather than passing a separate length value.

How to write to pointer directly using gets() function?

I got these test code and just curious, why passing pointer to gets() results in a runtime error?
void main()
{
char *value="gogo";
puts(value);
value="11";
puts(value);
gets(value);
}
Because char *value="gogo"; is more likely than not allocated to READ ONLY MEMORY!
Better:
#include <stdio.h>
#include <string.h>
#define MAX_LINE 80
int main()
{
char value[MAX_LINE] ="gogo";
puts(value);
strcpy (value, "11");
puts(value);
fgets(value, MAX_LINE, stdin);
puts(value);
return 0;
}
Here is a good link with more details: Storage for Strings in C
PS:
gets() is Evil. Avoid it if at all possible: Why gets() is bad
The pointer value points to (the static array associated with) a string literal.
Attempting to modify a string literal has undefined behavior. In this case, your compiler stores the string "gogo" in memory marked as read-only by the operating system, and attempting to modify it causes your program to crash.
If you declare a pointer to a string literal, you should define it as const:
const char *value = "gogo";
so the compiler will diagnose any attempt to modify it. Or, if you really want to modify the string, define it as an array:
char value[] = "gogo";
which the means that you can't assign a value to value, but you can use strcpy to update it.
Some more problems:
void main() is wrong [*]; the correct definition is int main(void). If you're using a book that told you to use void main(), please get a better one; its author does not know C very well.
Never use the gets function; it is inherently unsafe, and has been removed from the language. (It cannot guard against input longer than the array into which the value is stored.) You can use fgets instead; it's a bit more complicated to use, but it can be used safely.
You need to add
#include <stdio.h>
to the top of your source file to make these functions visible. If your compiler didn't complain about calls to undeclared functions, find out how to increase its warning level.
[*] Saying that void main() is wrong slightly overstates the case. A conforming compiler may permit it, and no compiler is required to complain about it, but there is no good reason to take advantage of that. int main(void) is always correct. Any C book or tutorial that advocates using void main() was almost certainly written by someone who does not know C well enough to be writing books or tutorials about it.
Here, your pointer points to a string literal ("gogo"). String literals are not guaranteed to be writable. You need to allocate your own memory:
char value[50] = "gogo";
...
gets(value);
However, this is not safe, as gets does not take the size of the buffer, and thus might overflow your buffer. (Which could also lead to a runtime error). NEVER use gets, as the manpage states:
BUGS
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Much better to allocate your own memory:
char user_input[200];
fgets(user_input, 200, stdin);
You might need to check user_input, to see if it ends with a newline. If it does, then fgets read a whole line. If it doesn't, then the the user typed more than ~200 characters into the line, and you'll need to read more to get the whole line. I've used 200 here. Choose a size that makes sense for your data. You can also use malloc to allocate memory on-the-fly, and put fgets into a loop in order to read an entire line into a buffer.

How strcpy works behind the scenes?

This may be a very basic question for some. I was trying to understand how strcpy works actually behind the scenes. for example, in this code
#include <stdio.h>
#include <string.h>
int main ()
{
char s[6] = "Hello";
char a[20] = "world isnsadsdas";
strcpy(s,a);
printf("%s\n",s);
printf("%d\n", sizeof(s));
return 0;
}
As I am declaring s to be a static array with size less than that of source. I thought it wont print the whole word, but it did print world isnsadsdas .. So, I thought that this strcpy function might be allocating new size if destination is less than the source. But now, when I check sizeof(s), it is still 6, but it is printing out more than that. Hows that working actually?
You've just caused undefined behaviour, so anything can happen. In your case, you're getting lucky and it's not crashing, but you shouldn't rely on that happening. Here's a simplified strcpy implementation (but it's not too far off from many real ones):
char *strcpy(char *d, const char *s)
{
char *saved = d;
while (*s)
{
*d++ = *s++;
}
*d = 0;
return saved;
}
sizeof is just returning you the size of your array from compile time. If you use strlen, I think you'll see what you expect. But as I mentioned above, relying on undefined behaviour is a bad idea.
http://natashenka.ca/wp-content/uploads/2014/01/strcpy8x11.png
strcpy is considered dangerous for reasons like the one you are demonstrating. The two buffers you created are local variables stored in the stack frame of the function. Here is roughly what the stack frame looks like:
http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Call_stack_layout.svg/342px-Call_stack_layout.svg.png
FYI things are put on top of the stack meaning it grows backwards through memory (This does not mean the variables in memory are read backwards, just that newer ones are put 'behind' older ones). So that means if you write far enough into the locals section of your function's stack frame, you will write forward over every other stack variable after the variable you are copying to and break into other sections, and eventually overwrite the return pointer. The result is that if you are clever, you have full control of where the function returns. You could make it do anything really, but it isn't YOU that is the concern.
As you seem to know by making your first buffer 6 chars long for a 5 character string, C strings end in a null byte \x00. The strcpy function copies bytes until the source byte is 0, but it does not check that the destination is that long, which is why it can copy over the boundary of the array. This is also why your print is reading the buffer past its size, it reads till \x00. Interestingly, the strcpy may have written into the data of s depending on the order the compiler gave it in the stack, so a fun exercise could be to also print a and see if you get something like 'snsadsdas', but I can't be sure what it would look like even if it is polluting s because there are sometimes bytes in between the stack entries for various reasons).
If this buffer holds say, a password to check in code with a hashing function, and you copy it to a buffer in the stack from wherever you get it (a network packet if a server, or a text box, etc) you very well may copy more data from the source than the destination buffer can hold and give return control of your program to whatever user was able to send a packet to you or try a password. They just have to type the right number of characters, and then the correct characters that represent an address to somewhere in ram to jump to.
You can use strcpy if you check the bounds and maybe trim the source string, but it is considered bad practice. There are more modern functions that take a max length like http://www.cplusplus.com/reference/cstring/strncpy/
Oh and lastly, this is all called a buffer overflow. Some compilers add a nice little blob of bytes randomly chosen by the OS before and after every stack entry. After every copy the OS checks these bytes against its copy and terminates the program if they differ. This solves a lot of security problems, but it is still possible to copy bytes far enough into the stack to overwrite the pointer to the function to handle what happens when those bytes have been changed thus letting you do the same thing. It just becomes a lot harder to do right.
In C there is no bounds checking of arrays, its a trade off in order to have better performance at the risk of shooting yourself in the foot.
strcpy() doesn't care whether the target buffer is big enough so copying too many bytes will cause undefined behavior.
that is one of the reasons that a new version of strcpy were introduced where you can specify the target buffer size strcpy_s()
Note that sizeof(s) is determined at run time. Use strlen() to find the number of characters s occupied. When you perform strcpy() source string will be replaced by destination string so your output wont be "Helloworld isnsadsdas"
#include <stdio.h>
#include <string.h>
main ()
{
char s[6] = "Hello";
char a[20] = "world isnsadsdas";
strcpy(s,a);
printf("%s\n",s);
printf("%d\n", strlen(s));
}
You are relying on undefined behaviour in as much as that the compiler has chose to place the two arrays where your code happens to work. This may not work in future.
As to the sizeof operator, this is figured out at compile time.
Once you use adequate array sizes you need to use strlen to fetch the length of the strings.
The best way to understand how strcpy works behind the scene is...reading its source code!
You can read the source for GLibC : http://fossies.org/dox/glibc-2.17/strcpy_8c_source.html . I hope it helps!
At the end of every string/character array there is a null terminator character '\0' which marks the end of the string/character array.
strcpy() preforms its task until it sees the '\0' character.
printf() also preforms its task until it sees the '\0' character.
sizeof() on the other hand is not interested in the content of the array, only its allocated size (how big it is supposed to be), thus not taking into consideration where the string/character array actually ends (how big it actually is).
As opposed to sizeof(), there is strlen() that is interested in how long the string actually is (not how long it was supposed to be) and thus counts the number of characters until it reaches the end ('\0' character) where it stops (it doesn't include the '\0' character).
Better Solution is
char *strcpy(char *p,char const *q)
{
char *saved=p;
while(*p++=*q++);
return saved;
}

Find the size of reserved memory for a character array in C

I'm trying to learn C and as a start, i set off writing a strcpy for my own practice. As we know, the original strcpy easily allows for security problems so I gave myself the task to write a "safe" strcpy.
The path I've chosen is to check wether the source string (character array) actually fits in the destination memory. As I've understood it, a string in C is nothing more than a pointer to a character array, 0x00 terminated.
So my challenge is how to find how much memory the compiler actually reserved for the destination string?
I tried:
sizeof(dest)
but that doesn't work, since it will return (as I later found out) the size of dest which is actually a pointer and on my 64 bit machine, will always return 8.
I also tried:
strlen(dest)
but that doesn't work either because it will just return the length until the first 0x0 is encountered, which doesn't necessarily reflect the actual memory reserved.
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
Example:
char s[80] = "";
int i = someFunction(s); // should return 80
What is "someFunction"?
Thanks in advance!
Once you pass a char pointer to the function you are writing, you will loose knowledge for how much memory is allocated to s. You will need to pass this size as argument to the function.
You can use sizeof to check at compile time:
char s[80] = "";
int i = sizeof s ; // should return 80
Note that this fails if s is a pointer:
char *s = "";
int j = sizeof s; /* probably 4 or 8. */
Arrays are not pointers. To keep track of the size allocated for a pointer, the program simply must keep track of it. Also, you cannot pass an array to a function. When you use an array as an argument to a function, the compiler converts that to a pointer to the first element, so if you want the size to be avaliable to the called function, it must be passed as a parameter. For example:
char s[ SIZ ] = "";
foo( s, sizeof s );
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
There is no portable way to find out how much memory is allocated. You have to keep track of it yourself.
The implementation must keep track of how much memory was malloced to a pointer, and it may make something available for you to find out. For example, glibc's malloc.h exposes
size_t malloc_usable_size (void *__ptr)
that gives you access to roughly that information, however, it doesn't tell you how much you requested, but how much is usable. Of course, that only works with pointers you obtained from malloc (and friends). For an array, you can only use sizeof where the array itself is in scope.
char s[80] = "";
int i = someFunction(s); // should return 80
In an expression s is a pointer to the first element of the array s. You cannot deduce the size of an array object with the only information of the value of a pointer to its first element. The only thing you can do is to store the information of the size of the array after you declare the array (here sizeof s) and then pass this information to the functions that need it.
There's no portable way to do it. However, the implementation certainly needs to know this information internally. Unix-based OSes, like Linux and OS X, provide functions for this task:
// OS X
#include <malloc/malloc.h>
size_t allocated = malloc_size(somePtr);
// Linux
#include <malloc.h>
size_t allocated = malloc_usable_size(somePtr);
// Maybe Windows...
size_t allocated = _msize(somePtr);
A way to tag the member returned by malloc is to always malloc an extra sizeof(size_t) bytes. Add that to the address malloc returns, and you have a storage space for storing the actual length. Store the malloced size - the sizeof (size_t) there, and you have the basis for your new set of functions.
When you pass two of these sorts of pointers into your new-special strcpy, you can subtract sizeof(size_t) off the pointers, and access the sizes directly. That lets you decide if the memory can be copied safely.
If you are doing strcat, then the two sizes, along with calculating the strlens means you can do the same sort of check to see if the results of the strcat will overflow the memory.
It's doable.
It's probably more trouble than it's worth.
Consider what happens if you pass in a character pointer that was not mallocated.
The assumption is that the size is before the pointer. That assumption is false.
Attempting to access the size in that case is undefined behavior. If you are lucky, you may get a signal.
One other implication of that sort of implementation is that when you go to free the memory, you have to pass in exactly-the-pointer-that-malloc-returned. If you don't get that right, heap corruption is possible.
Long story short...
Don't do it that way.
For situations where you are using character buffers in your program, you can do some smoke and mirrors to get the effect that you want. Something like this.
char input[] = "test";
char output[3];
if (sizeof(output) < sizeof(input))
{
memcpy(output,input,sizeof(input) + 1);
}
else
{
printf("Overflow detected value <%s>\n",input);
}
One can improve the error message by wraping the code in a macro.
#define STRCPYX(output,input) \
if (sizeof(output) < sizeof(input)) \
{ \
memcpy(output,input,sizeof(input) + 1); \
} \
else \
{ \
printf("STRCPYX would overflow %s with value <%s> from %s\n", \
#output, input, #input); \
} \
char input[] = "test";
char output[3];
STRCPYX(output,input);
While this does give you what you want, the same sort of risks apply.
char *input = "testing 123 testing";
char output[9];
STRCPYX(output,input);
the size of input is 8, and output is 9, the value of output ends up as "Testing "
C was not designed to protect the programmer from doing things incorrectly.
It is kind of like you are attempting to paddle upriver :)
It is a good exercise to think about.
Although arrays and pointers can appear to be interchangeable, they differ in one important aspect; an array has size. However because an array when passed to a function "degrades" to a pointer, the size information is lost.
The point is that at some point you know the size of the object - because you allocated it or declared it to be a certain size. The C language makes it your responsibility to retain and disseminate that information as necessary. So after your example:
char s[80] = ""; // sizeof(s) here is 80, because an array has size
int i = someFunction(s, sizeof(s)) ; // You have to tell the function how big the array is.
There is no "magic" method of determining the size of the array within someFunction(), because that information is discarded (for reasons of performance and efficiency - C is relatively low level in this respect, and does not add code or data that is not explicit); if the information is needed, you must explicitly pass it.
One way in which you can pass a string and retain size information, and even pass the string by copy rather than by reference is to wrap the string in a struct thus:
typedef struct
{
char s[80] ;
} charArray_t ;
then
charArray_t s ;
int i = someFunction( &s ) ;
with a definition of someFunction() like:
int someFunction( charArray_t* s )
{
return sizeof( s->s ) ;
}
You don't really gain much by doing that however - just avoid the additional parameter; in fact you loose some flexibility because someFunction() now only takes a fixed array length defined by charrArray_t, rather than any array. Sometimes such restrictions are useful. On feature of this approach is that you can pass by copy this:
int i = someFunction( s ) ;
then
int someFunction( charArray_t s )
{
return sizeof( s.s ) ;
}
since structures unlike arrays can be passed this way. You can equally return by copy as well. It can be somewhat inefficient however. Sometimes the convenience and safety outweigh the inefficiency however.

C: String manipulation adding more characters without causing a buffer overflow

In C I have a path in one of my strings
/home/frankv/
I now want to add the name of files that are contained in this folder - e.g. file1.txt file123.txt etc.
Having declared my variable either like this
char pathToFile[strlen("/home/frankv/")+1]
or
char *pathToFile = malloc(strlen("/home/frankv/")+1)
My problem is that I cannot simply add more characters because it would cause a buffer overflow. Also, what do I do in case I do not know how long the filenames will be?
I've really gotten used to PHP lazy $string1.$string2 .. What is the easiest way to do this in C?
If you've allocated a buffer with malloc(), you can use realloc() to expand it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *buf;
const char s1[] = "hello";
const char s2[] = ", world";
buf = malloc(sizeof s1);
strcpy(buf, s1);
buf = realloc(buf, sizeof s1 + sizeof s2 - 1);
strcat(buf, s2);
puts(buf);
return 0;
}
NOTE: I have omitted error checking. You shouldn't. Always check whether malloc() returns a null pointer; if it does, take some corrective action, even if it's just terminating the program. Likewise for realloc(). And if you want to be able to recover from a realloc() failure, store the result in a temporary so you don't clobber your original pointer.
Use std::string, if possible. Else, reallocate another block of memory and use strcpy and strcat.
You have a couple options, but, if you want to do this dynamically using no additional libraries, realloc() is the stdlib function you're looking for:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
char *string_to_add = "filename.txt";
char *p = realloc(pathToFile, strlen(pathToFile) + strlen(string_to_add) + 1);
if (!p) abort();
pathToFile = p;
strcat(p, string_to_add);
Note: you should always assign the result of realloc to a new pointer first, as realloc() returns NULL on failure. If you assign to the original pointer, you are begging for a memory leak.
If you're going to be doing much string manipulation, though, you may want to consider using a string library. Two I've found useful are bstring and ustr.
In case you can use C++, use the std::string. In case you must to use pure C, use what's call doubling - i.e. when out of space in the string - double the memory and copy the string into the new memory. And you'll have to use the second syntax:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
You have chosen the wrong language for manipulating strings!
The easy and conventional way out is to do something like:
#define MAX_PATH 260
char pathToFile[MAX_PATH+1] = "/home/frankv/";
strcat(pathToFile, "wibble/");
Of course, this is error prone - if the resulting string exceeds MAX_PATH characters, anything can happen, and it is this sort of programming which is the route many trojans and worms use to penetrate security (by corrupting memory in a carefully defined way). Hence my deliberate choice of 260 for MAX_PATH, which is what it used to be in Windows - you can still make Windows Explorer do strange things to your files with paths over 260 characters, possibly because of code like this!
strncat may be a small help - you can at least tell it the maximum size of the destination, and it won't copy beyond that.
To do it robustly you need a string library which does variable length strings correctly. But I don't know if there is such a thing for C (C++ is a different matter, of course).

Resources