Calling a function doesn't execute the print statement inside that function - c

Why is it that my first block of code doesn't output anything while the 2nd block does print out "hi"? I suspect that the program never goes into the test() function in the first block, but I don't know why that happens and how I should fix it.
P.S. I know that my codes don't really make any sense such as that the return value of the functions should be char *. This is because I haven't completed the function and I am still at the stage of testing what I have written. I think the return value of char * shouldn't be the reason for my problem, but do let me know if it is!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* test(char **strs, int strs_sz){
printf("%s", "hi");
}
int main(void){
char *arg[] = {"XX", "YY", "ZZ"};
char *all = test(arg, 1);
printf("%s\n", all);
free(all);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* fcn(char **para){
printf("%s", "hi");
}
int main(void){
char *arg[] = {"XX", "YY", "ZZ"};
char *s = fcn(arg);
}

To sum up what was already explained in the comments and fill in some blanks:
When using standard C library functions to work with files (printf actually works with a file stdout), the data is first cached in memory, and only written to the actual file when some condition is met:
The file is closed
The file is fflushed.
The memory buffer is full
etc.
In case of stdout, this will happen when the \n character is printed or when your program exists and the file is closed.
However, in your first code snippet you try to dereference (use) a pointer all.
Since you did not write a return statement in your test function, it is impossible to predict what value will end up being stored in all.
So, your program most likely crashes unexpectedly, and thus the buffer never gets written to stdout.
You should never test incomplete functions!
At the very least, build up a skeleton code that makes the function legal, such as a dummy return statement.
Otherwise, you will encounter "undefined behavior", which is another way of saying your program will react in weird and unpredictable ways.

Related

Compare encrypted strings with strcmp

I am trying to fill the gaps in my self-education in computer science and taking the CS50 course on Edx. I am completely new to C. In one of the problems sets, I have to compare strings encrypted with crypt function.
In the following example, I cannot understand why strcmp returns 0 (i.e. 'claims' that the strings are equal:
#include <crypt.h>
#include <stdio.h>
#include <string.h>
#define _XOPEN_SOURCE
int main(void)
{
char string1[4] = "foo\0";
char string2[4] = "bar\0";
printf("crypt1: %s\n",crypt(string1, "50\0"));
printf("crypt2: %s\n",crypt(string2, "50\0"));
if (strcmp(crypt(string1, "50\0"),crypt(string2, "50\0")) == 0)
{
printf("crypt1: %s\n",crypt(string1, "50\0"));
printf("crypt2: %s\n",crypt(string2, "50\0"));
return 0;
}
}
When I run the program, the output value is:
crypt1: 50GbL/FUeE/J6
crypt2: 50hmnpE.bRNiU
crypt1: 50GbL/FUeE/J6
crypt2: 50hmnpE.bRNiU
How is it possible, that the code inside if condition is even executed?
Apparently, crypt() uses the same buffer for the encrypted string on each call:
char string1[] = "foo";
char string2[] = "bar";
char *crypt1 = crypt(string1, "50");
printf("crypt1: %s\n", crypt1); // crypt1: 50GbL/FUeE/J6
char *crypt2 = crypt(string2, "50");
printf("crypt1: %s\n", crypt1); // crypt1: 50hmnpE.bRNiU
printf("crypt2: %s\n", crypt2); // crypt2: 50hmnpE.bRNiU
In order to keep (and compare) both results, you have to strdup()
them or copy them to a separate array.
As mentioned in Martin's comment, crypt returns a pointer to a static buffer that is overwritten on each call. So strcmp is actually being passed the same buffer - the first value of crypt already having been overwritten by the second - once the two arguments have been evaluated.
Related to the following: C crypt function, malloc and valgrind
[And, for what its worth, in C, any function that returns a string (char *) has to get the memory for that string from somewhere. You either need to pass the buffer in as an argument, or it needs to find it itself. And because C doesn't do garbage collection and requires manual memory management (e.g. malloc/free), a function that does not take a result buffer as an argument should throw up a red flag - is the result a static buffer (that gets overwritten like this)? does it need to be free'd when I'm done with it? Otherwise, you risk memory leaks or bugs like the one you're experiencing.)

Retrieve information using stack buffer overflow (C)

I found one interesting exercises on the net, it states that the specific input can overflow the buffer in such a way that the 'secret' will be printed to stdout.
I tried to figure it out by my self but I haven't done well.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_name(char *name, char *pr) {
char local[20];
printf("%s:",pr);
gets(local);// BUG
strncat(name,local,20);
}
int foo () {
char name[28]="Hello..";
char secret[12]="TOP SECRET";
char buf[24];
char n1[]="Enter your name";
char n2[]="Enter Secret code";
get_name(name,n1);
memset(buf, 0, sizeof(buf));
// Lets ONLY use strncpy for better control!!!
strncpy(buf, name, sizeof(buf));//BUG
printf("%s\n", buf);
memset(name,0,sizeof(name));
get_name(name, n2);
if (strncmp(secret,name,10)==0)
printf("Welcome and %s\n",buf);
else {printf("Wrong code, better try again..\n");}
return 0;
}
int main(int argc, char **argv)
{
foo();
printf("Bye\n");
return 0;
}
There is no way to know what the outcome of such buffer overflows will do. You can't know or assume what memory they will overwrite. Most likely they will only cause some sort of run-time crash. Any exploit would have to have a very specific system in mind. Which means that nobody would be able to answer your question without knowing the details of a given system.
What your "random internet person" is aiming for, is likely to overwrite the null termination of Hello.. with some garbage, so that the "TOP SECRET" string will get printed along with it. You can't assume that those two strings are allocated adjacently, however. You could try to type 28 letter long input to gets and see what happens... there are no guarantees of any given behavior. On my computer it does nothing exciting apart from printing some garbage. Reverse-engineering of my binary reveals that that's because the arrays are indeed not allocated adjacently.
In addition, your comments about strncpy are misguided, strncpy is dangerous and should be avoided, see this.

Char arrays and scanf function in C

I expected to get errors in following code, but I did not. I did not use & sign. Also I am editing array of chars.
#include <stdio.h>
int main()
{
char name[10] ="yasser";
printf("%s\n",name);
// there is no error ,
// trying to edit array of chars,
// also did not use & sign.
scanf("%s",name);
// did not use strcpy function also.
printf("%s\n",name);
return 0;
}
I expected to get errors in following code, but I did not.I did not use & sign.
scanf("%s",name);
That's totally ok as name is already the address of the character array.
It sounds like you have several questions:
calling scanf("%s", name) should have given an error, since %s expects a pointer and name is an array? But as others have explained, when you use an array in an expression like this, what you always get (automatically) is a pointer to the array's first element, just as if you had written scanf("%s", &name[0]).
Having scanf write into name should have given an error, since name was initialized with a string constant? Well, that's how it was initialized, but name really is an array, so you're free to write to it (as long as you don't write more than 10 characters into it, of course). See more on this below.
Characters got copied around, even though you didn't call strcpy? No real surprise, there. Again, scanf just wrote into your array.
Let's take a slightly closer look at what you did write, and what you didn't write.
When you declare and initialize an array of char, it's completely different than when you declare and initialize a pointer to char. When you wrote
char name[10] = "yasser";
what the compiler did for you was sort of as if you had written
char name[10];
strcpy(name, "yasser");
That is, the compiler arranges to initialize the contents of the array with the characters from the string constant, but what you get is an ordinary, writable array (not an unwritable, constant string constant).
If, on the other hand, you had written
char *namep = "yasser";
scanf("%s", namep);
you would have gotten the problems you expected. In this case, namep is a pointer, not an array. It's initialized to point to the string constant "yasser", which is not writable. When scanf tried to write to this memory, you probably would have gotten an error.
When you pass arrays to functions in C, they decay to pointers to the first item.
Therefore for:
char name[] ="yasser";
scanf("%s", name) is the same as scanf("%s", &name[0]) and either of those invocations should send shivers down your spine, because unless you control what's on your stdin (which you usually don't), you're reading a potentially very long string into a limited buffer, which is a segmentation fault waiting to happen (or worse, undefined behavior).
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char *myName = (char *) calloc(10, sizeof(char));
*(myName)='K'; *(myName+1)='h'; *(myName+2)='a'; *(myName+3)='l'; *(myName+4)='i'; *(myName+5)='d';
printf("%s\n",myName);
scanf("%s",myName);
printf("%s\n",myName);
return (EXIT_SUCCESS);
}
#include <stdio.h>
#include <string.h>
int main()//fonction principale
{
char name[10] ="yasser";
int longeur=0;
printf("%s\n",name);
scanf("%s",name);
longeur = strlen(name);
for (int i=0;i<longeur;i++) {
printf("%c",*(name+i));
}
return 0;}

Segmentation fault passing an address specifically defined as a string

Here's more code I whipped up since i was having trouble with my major program that I now fixed.
I have a function which modifies a series of bytes. In this example, the function is supposed to fill up the first 9 bytes of the char array with the numbers 1 through 9 consecutively.
Two tests are run. The first one is calling the function where the parameter is (char*)&myvar. The second test only uses myvar as a parameter. I thought I always had to use an & in front of a char array pointer when I want the string returned in the parameter portion of the function.
Why does this program only work when I don't prepend (char*)& to my char array variable?
When I do apply it, I receive a segmentation fault.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int func(char* abc){
char *p=abc;
int n;
for (n=1;n<10;n++){
*p=(unsigned char)(n+48);p++;
}
return 0;
}
int main(){
char vars[1000]="234";
char *myvar=vars;
printf("Function test\n");
int result=func((char*)&myvar); //causes segfault
printf("Function result %s\n",myvar); //segfault here
printf("Function test again\n");
int result2=func(myvar); //works
printf("Function result %s\n",myvar);
printf("DONE\n");
return 0;
}
Why does this program only work when I don't prepend (char*)& to my char array variable?
Because doing that is completely wrong and not a thing that makes sense.
I thought I always had to use an & in front of a char array pointer when I want the string returned in the parameter portion of the function.
You don't. (Also, you do not have a "char array pointer", and "when I want the string returned in the parameter portion of the function" doesn't make sense.)
When you need to pass a char * to a function that takes a char *, you do not need to put any special prefix in front of the pointer. You just pass it directly, the way you did with
int result2=func(myvar);
You could also have passed in vars, due to the automatic conversion from an array to a pointer to its first element, just like you were able to do char *myvar=vars; without any special casting.

how to assign a value to a string array?

for example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char substr[10][20];
int main() {
substr[0] = "abc";
printf("%d", substr[0]);
}
of course above is wrong? how to do it? thanks
You can't assign strings like that in C. Instead, use strcpy(substr[0], "abc"). Also, use %s not %d in your printf
I hate giving 'full' answers to homework questions, but the only way to answer your question is to show you the answer to your problem, because it is so basic:
#include <stdio.h>
#include <string.h>
#define MAXLEN 20
char substr[10][MAXLEN];
int main(void) {
strncpy(substr[0], "abc", MAXLEN);
puts(substr[0]);
return 0;
}
Your code (as is) has several faults:
You are treating substr[0] as a string literal. You can't do that.
You were using printf formatters incorrectly. %s is for strings
You don't need to bother printf() to print a string
You should (in real code) watch out for buffer overflows, hence strncpy()
If main() doesn't want / need argc and argv, its arguments should be void
main() should return a value, as its return type is int
You aren't using anything out of <stdlib.h>, why include it?
I suggest researching string literals, the functions available in <string.h> as well as format specifiers.
Also note, I am not checking the return of strncpy(), which is something you should be doing. That is left as an exercise for the reader.
Hope this helps:
void main(void)
{
char* string[10];
string[0] = "Hello";
}
Otherwise I think ya need to copy it by hand or use strcpy or the like to move it from one block of memory to another.

Resources