char s[100]={0};
fgets(s, sizeof(s), stdin);
In the context of the code above, what is the difference between these three?
printf("%s",s);
printf(s);
fputs(s,stdout);
printf("%s",s); correct but printf is a very heavy function and most compilers will actually replace it with puts in the compiler code if the format string ends with '\n'
printf(s); very dangerous as the format string may contain % and then it will expect another parameters. If it happens it is UB. It also makes your code exploit prone
fputs(s,stdout); OK. Not as heavy as printf but will add the new line
#2 Should NEVER be used. I won't even write it here. An evil input can do very bad things in your system by introducing special characters. New versions of gcc warn you about this bug.
The difference between
printf("%s", s);
and
puts(s)
is that puts will add a newline, just like if you called
printf("%s\n", s);
As mentioned by other comments and answers, do not try the second option. Also, the third one is quite lighter than the first one.
However, I still prefer the first option (printf() function) because it allows you to have a formatted string, which means you can print out almost any data type using this function, whereas the function fputs only accept strings. So in most cases, you will have to format the string first (maybe using sprintf()) before passing it to the function !
Related
Is this ever acceptable?
fprintf(fp,"Just a string");
or
fprintf(fp,stringvariable);
versus
fprintf(fp,"%s","Just a string");
It seems confusing to me as the string variable (or constant) is used as the formatting versus the output itself. It the string variable had format-specific content ('%s', etc.) then the output would not be as intended.
For string-only output (no formatting) which is better?
fprintf(fp,"%s",stringvariable);
or
fputs(stringvariable,fp);
It is acceptable if you "know" the string variable to be "clean", if you don't care about the warning most modern compilers generate for that construct. Because:
If your string contains conversion specifiers "by accident", you are invoking undefined behaviour.
If you read that string from somewhere, a malicious attacker could exploit point 1. above to his ends.
It's generally better to use puts() or fputs() as they avoid this problem, and consequently don't generate a warning. (puts() also tosses in an automatic '\n'.)
The *puts() functions also have (marginally) better performance. *printf(), even on nothing more than "%s" as format string, still has to parse that conversion specifier, and count the number of characters printed for its return value.
Thanks to users 'rici' and 'Grady Player' for pointing out the character counting and compiler warning. My C got a bit rusty it seems. ;-)
my question is about
gets()
and
puts()
are they a perfect solution for string input and output?
gets is marked as obsolescent in C99 and has been removed in C11 because of security issues with this function. Don't use it, use fgets instead. As an historical note, gets was exploited (in fingerd) by the first massive internet worm: the inet worm back in 1988.
puts function is OK if it fits your needs.
gets() is fundamentally insecure in a really horrific way: it will write an unlimited number of characters to its argument, overflowing any buffer it is provided. As such, it should never, ever be used. Many newer compilers will issue an automatic warning if you use it. Instead, use fgets(), which takes a length argument:
char buf[...];
fgets(buf, sizeof(buf), stdin);
On the other hand, puts() is totally fine. It's equivalent to printf("%s\n", x);, and some compilers will in fact convert certain constant printf() calls to puts() as a standard optimization. Go wild.
For gets, see the man page:
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.
puts is fine, if you're just looking to write a string to stdout.
please take a look at the two following c statements
printf("a very long string");
printf("%s","a very long string");
they produce the same result,but there is definitely some difference under the hood,so what is the difference and which one is better? Please share your ideas!
If you know what the string contents are, you should use the first form because it is more compact. If the string you want to print can come from the user or from any other source such that you do not know what the string contents are, you must use the second form; otherwise, your code will be wide open to format string injection attacks.
The first printf works like this
'a' is not a special character: print it
' ' is not a special character: print it
'v' is not a special character: print it
...
'g' is not a special character: print it
The second printf works like this
'%' is a special character:
's' print the contents of the string pointed to by the 2nd parameter
The first one passes one parameter and the second passes 2, so the call is slightly faster in the first one.
But in the first one, printf() has to scan the long string for format specifications and in the second one, the format string is very short, so the actual processing is probably faster in the second one.
More important (to me anyway), is that "a very long string" is not likely to be a a constant string as it is in this example. If you're printf'ing a long string, you're probably using a pointer to to something that the program generated. In that case, it's a MUCH better idea to use the second form because otherwise somewhere, somehow, sometime, the long string will contain a format printf format specification and that will cause printf to go looking for another argument and your program will crash. This exact problem just happened to me about a week ago in code that we have been using for nearly 20 years.
The bottom line is that your printf format specification should always be a constant string. If you need to output a variable, use printf("%s",var) or better yet, fputs(var, stdout).
The first is no less efficient than the second. Since there are no format sequences and no corresponding arguments, no work must be done by the printf() function. In the second case, if the compiler isn't smart enough to catch this, you will be calling for unnecessary work (note: miniscule compared to actually sending (and reading!) the output at the terminal.
printf was designed for printing with formatting. It is more useful to provide formatting arguments for the sake of debugging although they aren't required.
%s takes a value of a const char* whereas leaving no argument just prints the literal expression.
You could still cast a different pointer to the const char* explicitly and change its contents without changing the output expression.
First of all you should define "better" better since it is not smart enough by itself. Better in what way? performance, maintenance, readibility, extensibilty ...
With the one line of code presented I would choose option 1 for almost all versions of 'better'
It's more readible
It does what it should do and nothing more (KISS principle)
It's faster (no pointless moving memory around to stuff one string into another). But unless you are doing this printf a hell of a lot of times in a loop this is not that a big plus.
I am writing a fuzzer that using the system() function and I need to copy:
char a[1100]; /* full of A's with null ending */
into:
char tmp[10000];
I used:
sprintf(tmp, "%s", a);
When I printf tmp there is nothing printed. What am I doing wrong?
There's no way to say what you are doing wrong without seeing the whole thing.
The above sprintf should work, although strcpy would make more sense for that purpose. I'd guess that sprintf works fine. Could be that your a array is not "full of A's" as you believe, but rather an empty string (full of zeros). Or maybe it is your printing that either doesn't work or it works but you don't see the output for some reason.
My bet would be that your a is an empty string. No A's there. Where and how do you put those A's into the a array?
Output is often line-buffered. If the string you're printing has no newline, you might not see it without calling fflush first (also see http://c-faq.com/stdio/fflush.html). But as AndreyT said, we can't tell without seeing the rest of your code.
From man gets:
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.
Almost everywhere I see scanf being used in a way that should have the same problem (buffer overflow/buffer overrun): scanf("%s",string). This problem exists in this case? Why there are no references about it in the scanf man page? Why gcc does not warn when compiling this with -Wall?
ps: I know that there is a way to specify in the format string the maximum length of the string with scanf:
char str[10];
scanf("%9s",str);
edit: I am not asking to determe if the preceding code is right or not. My question is: if scanf("%s",string) is always wrong, why there are no warnings and there is nothing about it in the man page?
The answer is simply that no-one has written the code in GCC to produce that warning.
As you point out, a warning for the specific case of "%s" (with no field width) is quite appropriate.
However, bear in mind that this is only the case for the case of scanf(), vscanf(), fscanf() and vfscanf(). This format specifier can be perfectly safe with sscanf() and vsscanf(), so the warning should not be issued in that case. This means that you cannot simply add it to the existing "scanf-style-format-string" analysis code; you will have to split that into "fscanf-style-format-string" and "sscanf-style-format-string" options.
I'm sure if you produce a patch for the latest version of GCC it stands a good chance of being accepted (and of course, you will need to submit patches for the glibc header files too).
Using gets() is never safe. scanf() can be used safely, as you said in your question. However, determining if you're using it safely is a more difficult problem for the compiler to work out (e.g. if you're calling scanf() in a function where you pass in the buffer and a character count as arguments, it won't be able to tell); in that case, it has to assume that you know what you're doing.
When the compiler looks at the formatting string of scanf, it sees a string! That's assuming the formatting string is not entered at run-time. Some compilers like GCC have some extra functionality to analyze the formatting string if entered at compile time. That extra functionality is not comprehensive, because in some situations a run-time overhead is needed which is a NO NO for languages like C. For example, can you detect an unsafe usage without inserting some extra hidden code in this case:
char* str;
size_t size;
scanf("%z", &size);
str = malloc(size);
scanf("%9s"); // how can the compiler determine if this is a safe call?!
Of course, there are ways to write safe code with scanf if you specify the number of characters to read, and that there is enough memory to hold the string. In the case of gets, there is no way to specify the number of characters to read.
I am not sure why the man page for scanf doesn't mention the probability of a buffer overrun, but vanilla scanf is not a secure option. A rather dated link - Link shows this as the case. Also, check this (not gcc but informative nevertheless) - Link
It may be simply that scanf will allocate space on the heap based on how much data is read in. Since it doesn't allocate the buffer and then read until the null character is read, it doesn't risk overwriting the buffer. Instead, it reads into its own buffer until the null character is found, and presumably copies that buffer into another of the correct size at the end of the read.