sprintf behavies different than printf

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • google@pekspro.com

    sprintf behavies different than printf

    Consider the following code:

    char str[100];
    char str2[100];
    strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
    printf("printf: ");
    printf("1%s2", str);
    printf("\nsprin tf: ");
    sprintf(str2, "1%s2", str); //Interesting stuff happens here
    printf(str2);
    printf("\n");

    The code should format the string "1%s2" by replacing %s with "%alfa%
    %beta% d%100%d %gamma% %delta%". First printf is used, and then
    sprintf. The output should be:

    printf: 1%alfa% %beta% d%100%d %gamma% %delta%2
    sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2

    However, this is not what happens i either Visual C++ 6.0, Visual C++
    2003 and GCC (version 4 I think, compiled and tested in Linux). In all
    these compilers printf works as expected, but fails with sprintf where
    the result is either a crash or a malformed string. The problem seems
    to be that the %-character is used in the argument which, as fair as I
    know, shouldn't be any problem.

    If I replace %s with "%%alfa%% %%beta%% d%%100%%d %%gamma%% %%delta%%"
    the output will instead by (at least in Visual C++ 2003):

    printf: 1%%alfa%% %%beta%% d%%100%%d %%gamma%% %%delta%%2
    sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2

    So when using sprintf %% is replaced by % which should be the is these
    characters where written in the format string, but this is a very
    different case.

    Unless I have misunderstand the specification of sprintf there is a
    quite critical bug in sprintf and this in several compilers. Is this
    an known problem? Are more compilers affected? Why are the problem in
    both Visual C++ and GCC? Isn't this very interesting? :-)

    PEK
  • Eric Sosman

    #2
    Re: sprintf behavies different than printf

    google@pekspro. com wrote:
    Consider the following code:
    >
    char str[100];
    char str2[100];
    strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
    printf("printf: ");
    printf("1%s2", str);
    printf("\nsprin tf: ");
    sprintf(str2, "1%s2", str); //Interesting stuff happens here
    Not very. What happens on the next line is far more
    interesting, if undefined behavior is "interestin g" to you.
    printf(str2);
    This is equivalent to

    printf("1%alfa% %beta% d%100%d %gamma% %delta%2");

    .... which is faulty on several counts: Undefined conversion
    specifiers ("%a", "% ", "%b", "%100%", "%2"), and specifiers
    without values for them to convert ("%g", "%d"). printf()
    can do whatever it pleases; Garbage In, Garbage Out.

    --
    Eric.Sosman@sun .com

    Comment

    • Ben Pfaff

      #3
      Re: sprintf behavies different than printf

      google@pekspro. com writes:
      Consider the following code:
      >
      char str[100];
      char str2[100];
      strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
      printf("printf: ");
      printf("1%s2", str);
      printf("\nsprin tf: ");
      sprintf(str2, "1%s2", str); //Interesting stuff happens here
      printf(str2);
      You mean:
      printf("%s", str2);
      Otherwise the % directives in str2 are interpreted by printf(),
      with undefined results.
      printf("\n");
      --
      char a[]="\n .CJacehknorstu" ;int putchar(int);in t main(void){unsi gned long b[]
      ={0x67dffdff,0x 9aa9aa6a,0xa77f fda9,0x7da6aa6a ,0xa67f6aaa,0xa a9aa9f6,0x11f6} ,*p
      =b,i=24;for(;p+ =!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
      2:{i++;if(i)bre ak;else default:continu e;if(0)case 1:putchar(a[i&15]);break;}}}

      Comment

      • Martin Ambuhl

        #4
        Re: sprintf behavies different than printf

        google@pekspro. com wrote:
        Consider the following code:
        [replaced with the legal program, with one extra line:]
        #include <stdio.h>
        #include <string.h>

        int main(void)
        {
        char str[100];
        char str2[100];
        strcpy(str, "%alfa% %beta% d%100%d %gamma% %delta%");
        printf("printf: ");
        printf("1%s2", str);
        printf("\nsprin tf: ");
        sprintf(str2, "1%s2", str); /* Interesting stuff happens here */
        printf(str2);
        printf("\n");
        printf("%s\n", str2); /* the extra line */
        return 0;
        }
        The code should format the string "1%s2" by replacing %s with "%alfa%
        %beta% d%100%d %gamma% %delta%". First printf is used, and then
        sprintf. The output should be:
        >
        printf: 1%alfa% %beta% d%100%d %gamma% %delta%2
        sprintf: 1%alfa% %beta% d%100%d %gamma% %delta%2
        No, it should not. The format string in printf(str2) is
        "1%alfa% %beta% d%100%d %gamma% %delta%2"
        This format string tells printf to expect several additional arguments:
        "%a" (in C99) specifies a double to be represented with
        hex digits.
        (in C90) undefined conversion
        "% " undefined (no space is allowed as a flag in "%%")
        "%b" undefined conversion
        "% d" signed int represented as decimal integer with a leading space
        or '-'
        "%100" undefined
        "%d" signed int represented as decimal integer
        "%g" double represented as with "%f" or "%e"
        "% " undefined (no space is allowed as a flag in "%%")
        "%d" signed int represented as decimal integer
        "%2" undefined (no conversion specified, width = 2)

        You provide none of these arguments.
        See the result of the added line/


        Your various guesses are irrelevant. You call printf with a format
        string specifying additional atguments which you do not provide.

        Comment

        Working...