Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the input and output strings to sprintf() be the same?

Tags:

I have used this type of convention many times in my code in the past:

strcpy ( cTmpA, "hello" ); sprintf ( cTmpA, "%s world", cTmpA ); 

Recently I switched my legacy C compiler to Visual Studio 2005, and found I got a garbled string resulting from the above code. It then occurred to me that perhaps the behaviour of sprintf() is not rigidly defined where one of the inputs matches the output string.

Is the above code valid K&R C? If not, how do I find all the places in my code where this type of call to sprintf() has occurred?

like image 605
Piers Avatar asked Dec 29 '09 08:12

Piers


People also ask

Will sprintf overwrite?

You're overwriting the content of the file every time because you're using mode w to write the file, which re-writes the file from the beginning. If you simply want to append your data to the end of the file, you should use mode a like this: fptr=fopen("program.

Is sprintf vulnerable to buffer overflow?

The sprintf() function facilitates unbounded copying of text, in turn leaving the buffer susceptible to overflow attack.

How does sprintf work in C?

sprintf() in C sprintf stands for "string print". In C programming language, it is a file handling function that is used to send formatted output to the string. Instead of printing on console, sprintf() function stores the output on char buffer that is specified in sprintf.


2 Answers

While it is valid K&R C, you probably want to rather know if it's valid POSIX - see sprintf Specification. We read:

If copying takes place between objects that overlap as a result of a call to sprintf() or snprintf(), the results are undefined.

like image 181
Kornel Kisielewicz Avatar answered Sep 28 '22 04:09

Kornel Kisielewicz


Most implementations of sprintf() don't copy the format string and instead use a pointer inside the string you passed. If format and output point to the same memory, that will lead to odd results.

And you should really use snprintf() which protects you against buffer overflows.

To find all calls, put #define sprintf +++ into a common header find and recompile all sources. That should give you a list of errors along with the file name and line numbers :) Or use recursive search'n'replace of your IDE.

If you want to trim this list down to the ones where you use the same pointer for both arguments, use this macro:

#define sprintf(output,format,...) check_sprintf(__FILE__,__LINE__,output,format,....) 

Note that not all compilers support macros with varargs. Then define a new function check_sprintf:

int check_sprintf (char*filename,int line,char*output,char*format,...) {     va_list args;     int len;      if(output==format) {         fprintf(stderr,              "Output and format are the same at %s:%d", filename, line);              abort();     }      va_start (args, format);     len = vsprintf (output, format, args);     va_end (args);      return len;    } 

[EDIT] I just saw that you're talking about the output and the first argument. You can reuse the code from above and call va_arg() to get the first argument and use that in the compare.

like image 37
Aaron Digulla Avatar answered Sep 28 '22 05:09

Aaron Digulla