sprintf behavies different than printf

Discussion in 'C Programming' started by google@pekspro.com, Mar 14, 2008.

  1. Guest

    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("\nsprintf: ");
    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
     
    , Mar 14, 2008
    #1
    1. Advertising

  2. Eric Sosman Guest

    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("\nsprintf: ");
    > 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 "interesting" 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, Mar 14, 2008
    #2
    1. Advertising

  3. Ben Pfaff Guest

    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("\nsprintf: ");
    > 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);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,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)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
     
    Ben Pfaff, Mar 14, 2008
    #3
  4. On Fri, 14 Mar 2008 13:38:21 -0700 (PDT),
    <> 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("\nsprintf: ");
    > sprintf(str2, "1%s2", str); //Interesting stuff happens here
    > printf(str2);


    This line is the problem. Not the previous one.

    What you're trying to do is

    printf("%s", str2);

    What you're doing is passing str2 as the format specifier to printf,
    which means it will try to parse and interpret it as such, with many
    problems and undefined results due to invalid format specifications and
    missing parameters.

    > 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? :)


    It is probably not a good idea to assume that there is a bug in a
    compiler or library, especially not if other compilers support its
    behaviour, until you are 100% certain that you're right, and those
    compilers are wrong. Apart from anything else, it just means that you
    waste your time chasing red herrings.

    Regards,
    Martien
    --
    |
    Martien Verbruggen | The world is complex; sendmail.cf reflects
    | this.
    |
     
    Martien Verbruggen, Mar 14, 2008
    #4
  5. 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("\nsprintf: ");
    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.
     
    Martin Ambuhl, Mar 14, 2008
    #5
  6. Doug Miller Guest

    In article <>, wrote:
    >Consider the following code:


    [crap snipped]

    >Unless I have misunderstand the specification of sprintf there is a
    >quite critical bug in sprintf and this in several compilers.


    Upon sober reflection, which of these circumstances seems to you to be the
    more likely of the two?
     
    Doug Miller, Mar 15, 2008
    #6
  7. Guest

    On 14 Mar, 21:38, wrote:
    > [A lot of stupid things]


    Thanks for all replies that made me feel embarrassed, stupid, and more
    embarrassed. To all compilers I just can say:

    while(1)
    {
    printf("I'm sorry!\n");
    printf("I will never blame you again.\n");
    printf("You make beautiful and prefect things, and I make bugs.\n");
    printf("I'm sorry again, please forgive me for my evil words.\n");
    printf("You are the master, and I'm the stupid slave.\n\n");
    }

    I really should know better than this. I will never make any more
    premature conclusions (at least not this week).

    PEK
     
    , Mar 15, 2008
    #7
  8. said:

    > On 14 Mar, 21:38, wrote:
    >> [A lot of stupid things]

    >
    > Thanks for all replies that made me feel embarrassed, stupid, and more
    > embarrassed.


    Yes, it can be a bit face-reddening, can't it? Generally speaking, The
    Compiler Is Always Right. This isn't actually true, but it's a very useful
    lie with considerable explanatory power. Of course compilers have bugs -
    but the number of bugs in mainstream compilers or standard libraries that
    are likely to be first reported by a relatively inexperienced programmer
    is vanishingly small.

    In general, then, if you and the implementation disagree, you may safely
    assume that you are wrong.

    War story: when Visual Studio 6 was relatively fresh and exciting, a *very*
    inexperienced programmer showed me this program, which he'd copied from
    K&R2:

    #include <stdio.h>

    /* count characters in input: first version */
    main()
    {
    long nc;
    nc = 0;
    while (getchar() != EOF)
    ++nc;
    printf("%ld\n", nc);
    }

    He could not get it to produce any output. I smiled, and explained how to
    trigger the loop condition with ^Z, and he said that actually he happened
    to know about that, and in any case it wouldn't produce any output even
    when data was redirected in from a file.

    He was convinced that he had somehow mistyped something, and had compared
    every single character to the K&R2 original. He'd changed spacing, used
    tabs, changed the tab size on his editor - everything. He couldn't see
    what he'd done wrong, but he was sure he'd done *something* wrong.

    You know where I'm headed with this, I'm sure. The bug was fixed in
    Microsoft's next Visual Studio Service Pack.

    So yes, inexperienced programmers do sometimes find bugs in
    implementations. But it doesn't happen much more often than Patent Office
    clerks win Nobel Prizes.

    An experienced programmer will assume, in the first instance, that his or
    her code is wrong (because, in his or her experience, that is the most
    likely explanation). It is only after much head-scratching ("that's
    funny"), puzzled discussions with colleagues ("what's wrong with this
    code?"), and detailed consultations with experts in the field ("well, /I/
    can't see anything wrong with my code, but there must be something wrong
    with it - how about it, folks?"), that he or she might eventually conclude
    that the compiler or the library implementation is in error.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Mar 15, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ben
    Replies:
    4
    Views:
    621
    Martin Ambuhl
    Jun 26, 2004
  2. whatluo

    (void) printf vs printf

    whatluo, May 26, 2005, in forum: C Programming
    Replies:
    29
    Views:
    1,248
  3. azza

    printf affects following printf/s

    azza, Oct 17, 2010, in forum: C Programming
    Replies:
    0
    Views:
    433
  4. Replies:
    4
    Views:
    191
    Leslie Viljoen
    Jul 29, 2006
  5. Jian Lin
    Replies:
    1
    Views:
    92
    Roger Pack
    May 5, 2010
Loading...

Share This Page