Menu

sprintf(...) behaviour

2010-04-19
2012-09-26
  • charles elsaesser

    Hello,

    using
    Compiler: mingw-gcc-3.4.5 msvcrt60
    Executing g++.exe...
    i obtained a surprising behaviour of sprintf.

    Though norm C98/99 warns about overlapping objects, there is no warning on
    overlapping when executing some sprintf(...) applications.

    7.19.6.6 The sprintf function
    Synopsis
    1 #include <stdio.h>
    int sprintf(char * restrict s,
    const char * restrict format, ...);
    Description
    2 The sprintf function is equivalent to fprintf, except that the output is
    written into
    an array (specified by the argument s) rather than to a stream. A null
    character is written
    at the end of the characters written; it is not counted as part of the
    returned value. If
    copying takes place between objects that overlap, the behavior is undefined. </stdio.h>

    In the following code sequence
    rc1 = sprintf( str1, " aaa\n");
    rc1 = sprintf( str1, "\n%s bbb\n", str1);
    is very different from that one
    rc2 = sprintf( str2, " aaa\n\n");
    rc2 = sprintf( str2, "%s bbb\n", str2);

    Though the second construction well works, the difference is not very
    understandable, without the c98/99 norm warning.

    Is there a logical explanation here?

    See the C-like example

    ==>code

    int main( int argc, char argv, char envp )
    {
    char str1;
    char str2;
    int rc1;
    int rc2;

    / case 1 /
    fprintf(stdout, " --> case 1\n");
    memset( str1, 0, sizeof( str1)) ;
    rc1 = sprintf( str1, " aaa\n");
    fprintf( stdout, " rc1 = %d ( executing : rc1 = sprintf( str1, \"
    aaa\n\");)\n", rc1);
    image_zone( ( unsigned char ) str1 , sizeof( str1) , 16, -1L, "str1",
    stdout);
    rc1 = sprintf( str1, "\n%s bbb\n", str1);
    fprintf( stdout, " rc1 = %d ( executing : rc1 = sprintf( str1, \"\n%%s
    bbb\n\", str1);)\n", rc1);
    image_zone( ( unsigned char
    ) str1 , sizeof( str1) , 16, -1L, "str1",
    stdout);
    rc1 = sprintf( str1, "%s ccc.", str1);
    fprintf( stdout, " rc1 = %d ( executing : rc1 = sprintf( str1, \"%%s ccc.\",
    str1);)\n", rc1);
    image_zone( ( unsigned char *) str1 , sizeof( str1) , 16, -1L, "str1",
    stdout);
    fprintf( stdout, "\n%s\n", str1);

    fprintf(stdout, "--------------------------------------------------------\n");

    / case 2 /
    fprintf(stdout, " --> case 2\n");
    memset( str2, 0, sizeof( str2)) ;
    rc2 = sprintf( str2, " aaa\n\n");
    fprintf( stdout, " rc2 = %d ( executing : rc2 = sprintf( str2, \"
    aaa\n\n\");)\n", rc2);
    image_zone( ( unsigned char ) str2 , sizeof( str2) , 16, -1L, "str2",
    stdout);
    rc2 = sprintf( str2, "%s bbb\n", str2);
    fprintf( stdout, " rc2 = %d ( executing : rc2 = sprintf( str2, \"%%s bbb\n\",
    str2);)\n", rc2);
    image_zone( ( unsigned char
    ) str2 , sizeof( str2) , 16, -1L, "str2",
    stdout);
    rc2 = sprintf( str2, "%s ccc.", str2);
    fprintf( stdout, " rc2 = %d ( executing : rc2 = sprintf( str2, \"%%s ccc.\",
    str2);)\n", rc2);
    image_zone( ( unsigned char *) str2 , sizeof( str2) , 16, -1L, "str2",
    stdout);
    fprintf( stdout, "\n%s\n", str2);

    exit( 0);

    } / int main( int argc, char argv, char envp ) /

    ==>output

    . --> case 1
    . rc1 = 5 ( executing : rc1 = sprintf( str1, " aaa\n");)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff50" : "str1"
    . 0023ff50 .. 20616161 0a000000 00000000 00000000 . aaa
    . 0023ff60 .. 00000000 00000000 00000000 00000000 .
    . rc1 = 12 ( executing : rc1 = sprintf( str1, "\n%s bbb\n", str1);)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff50" : "str1"
    . 0023ff50 .. 0a0a0a0a 0a0a2020 6262620a 00000000 . bbb
    . 0023ff60 .. 00000000 00000000 00000000 00000000 .
    . rc1 = 18 ( executing : rc1 = sprintf( str1, "%s ccc.", str1);)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff50" : "str1"
    . 0023ff50 .. 0a0a0a0a 0a0a2020 6262620a 20206363 . bbb cc
    . 0023ff60 .. 632e0000 00000000 00000000 00000000 . c.
    .
    .
    .
    .
    .
    .
    .
    . bbb
    . ccc.
    .--------------------------------------------------------
    . --> case 2
    . rc2 = 6 ( executing : rc2 = sprintf( str2, " aaa\n\n");)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff30" : "str2"
    . 0023ff30 .. 20616161 0a0a0000 00000000 00000000 . aaa
    . 0023ff40 .. 00000000 00000000 00000000 00000000 .
    . rc2 = 12 ( executing : rc2 = sprintf( str2, "%s bbb\n", str2);)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff30" : "str2"
    . 0023ff30 .. 20616161 0a0a2020 6262620a 00000000 . aaa bbb
    . 0023ff40 .. 00000000 00000000 00000000 00000000 .
    . rc2 = 18 ( executing : rc2 = sprintf( str2, "%s ccc.", str2);)
    . image en base 16 ( groupes de 4 octets, 2 caracteres par octet) de la zone
    . "0x0023ff30" : "str2"
    . 0023ff30 .. 20616161 0a0a2020 6262620a 20206363 . aaa bbb cc
    . 0023ff40 .. 632e0000 00000000 00000000 00000000 . c.
    .
    . aaa
    .
    . bbb
    . ccc.

     
  • cpns

    cpns - 2010-04-19

    Is there a question in there somewhere?

     
  • cpns

    cpns - 2010-04-19

    Post your code in code markup!

    Note that Dev-C++ is merely an IDE not a compiler; if you need to know how the
    compiler handles such situations the documentation is
    here. There are many options for controlling
    warnings. I suggest that you use at least

    -Wformat -Wall -Werror
    

    The MSVCRT library documentation for sprintf() is
    here.

    The "logical explanation" is simply that undefined behaviour is undefined
    behaviour. The function need not be coded to deal with the situation in a
    consistent manner at all, because the situation would not be considered in its
    design.

    Moreover within the function, the array arguments will 'decay' to pointers
    with no size information so overlapping cannot be detected within the
    function.

     
  • cpns

    cpns - 2010-08-16

    @finnyalex: You have responded to a great many posts in a very short time. I
    suggest that you moderate your activity; many of these threads are old and
    have already been adequately answered.

    I also suggest that you loose the URL in your signature; many of your posts
    look more like an attempt to advertise your site rather than provide useful
    content. This particular post is just one such example; you have added no
    useful information whatsoever. In fact you simply repeated what I had already
    said.

     

Log in to post a comment.