2nd Underhanded C Contest Begins

Discussion in 'C Programming' started by Xcott Craver, Apr 5, 2006.

  1. Xcott Craver

    Xcott Craver Guest

    The second Underhanded C contest just opened today, and will run until
    July 4th. The Prize is a ThinkGeek gift certificate.

    The object is to write deceptive C code, code that does something
    malicious but looks innocent and simple enough to pass a cursory
    examination of the source.

    Last year's contest was to write an image processing routine that
    covertly embedds fingerprints in the images it creates. This year's
    challenge is to write C code that runs fine on one OS but mysteriously
    slowly on a competing OS.

    --
    "Old country music stars don't die -- they just get put in a coffin and buried
    in the ground and then no one sees them ever again."
    --Cat and Girl
    Xcott Craver, Apr 5, 2006
    #1
    1. Advertising

  2. Xcott Craver

    Xcott Craver Guest

    Xcott Craver <> wrote:
    >The second Underhanded C contest just opened today, and will run until
    >July 4th. The Prize is a ThinkGeek gift certificate.


    Dang-nabbit, I forgot the URL: http://www.brainhz.com/underhanded/

    --
    "Old country music stars don't die -- they just get put in a coffin and buried
    in the ground and then no one sees them ever again."
    --Cat and Girl
    Xcott Craver, Apr 5, 2006
    #2
    1. Advertising

  3. Xcott Craver wrote:
    > This year's
    > challenge is to write C code that runs fine on one OS but mysteriously
    > slowly on a competing OS.


    void setnormalcount(uint8 *count) {
    count = 3;
    }

    const uint32 count = 0;
    #ifdef NDEBUG
    setnormalcount(&count);
    #endif

    while(count--) {
    do_some_normal_task();
    }
    Sebastian Gottschalk, Apr 5, 2006
    #3
  4. Xcott Craver

    Guest

    Sebastian Gottschalk wrote:
    > Xcott Craver wrote:
    > > This year's
    > > challenge is to write C code that runs fine on one OS but mysteriously
    > > slowly on a competing OS.

    >
    > void setnormalcount(uint8 *count) {
    > count = 3;
    > }


    That should be *count = 3;

    > const uint32 count = 0;
    > #ifdef NDEBUG
    > setnormalcount(&count);


    This will warning out.

    > #endif


    It's probably valid to assume count=0 at this point and the compiler
    may optimize out this loop.

    > while(count--) {
    > do_some_normal_task();
    > }


    GCC 3.4.6 won't even compile this. It complains that decrementing
    count is invalid.

    And yes, GCC will allow you to overwrite 'count' but assumes it's zero.

    For instance

    void p(unsigned char *t) { *t = 3; }
    const unsigned r = 0;
    void q(void) { p(&r); if (r) printf("Whoa!\n"); }

    produces [on my amd64]

    p:
    ..LFB2:
    movb $3, (%rdi)
    ret
    ..LFE2:
    .size p, .-p
    .p2align 4,,15
    ..globl q
    .type q, @function
    q:
    ..LFB3:
    movl $r, %edi
    jmp p

    So clearly the printf is totally ignored.

    Tom
    , Apr 5, 2006
    #4
  5. wrote:

    > That should be *count = 3;


    Jupp, sorry.

    >> const uint32 count = 0;
    >> #ifdef NDEBUG
    >> setnormalcount(&count);

    >
    > This will warning out.
    >
    >> #endif

    >
    > It's probably valid to assume count=0 at this point and the compiler
    > may optimize out this loop.


    It's probably valid to assume that the symbol NDEBUG (== no debug) is
    defined and the this preprocessing statement justifies the use of th
    setnormalcount() function (which would be inlined).

    > GCC 3.4.6 won't even compile this. It complains that decrementing
    > count is invalid.


    Stupid me, if course the post-decrement means that count shouldn't be const.

    > So clearly the printf is totally ignored.


    With the little correction done, it does the printf 2 times.
    But well, compile it with a different endianess and you'll see why the
    difference between uint8 and uint32 is an important detail. :)
    Sebastian Gottschalk, Apr 5, 2006
    #5
  6. wrote:
    > GCC 3.4.6 won't even compile this. ...


    No conforming C compiler will accept the code as is,
    because the identifiers "uint8" and "uint32" aren't
    defined.
    Douglas A. Gwyn, Apr 5, 2006
    #6
  7. In article <>,
    Sebastian Gottschalk <> wrote:

    >With the little correction done, it does the printf 2 times.
    >But well, compile it with a different endianess and you'll see why the
    >difference between uint8 and uint32 is an important detail. :)


    Hmmm, the result would depend on the endianness. Endianness is
    a property of the processor + operating system combination, not
    necessarily of the operating system by itself.

    But either endianess, the program would still meet the criteria
    of operating at different speeds in different environment.
    --
    Programming is what happens while you're busy making other plans.
    Walter Roberson, Apr 5, 2006
    #7
  8. Xcott Craver

    Joe Estock Guest

    Xcott Craver wrote:
    > The second Underhanded C contest just opened today, and will run until
    > July 4th. The Prize is a ThinkGeek gift certificate.
    >
    > The object is to write deceptive C code, code that does something
    > malicious but looks innocent and simple enough to pass a cursory
    > examination of the source.


    [snip]

    Does this qualify? :)

    Hint: this compiles cleanly and runs just fine - just one problem. Can
    you find out what the problem is without compiling and running it?

    #include <stdio.h>
    #include <string.h>

    int main(void)
    {
    char buffer[600000];
    char piece[10];
    long i;

    strcpy(buffer, "");

    for(i = 0; i <= 199999; i++)
    {
    sprintf(piece, "%ld", i);
    strcat(buffer, piece);
    }

    printf("5=%d\n", strlen(buffer));

    return(0);
    }
    Joe Estock, Apr 6, 2006
    #8
  9. Xcott Craver

    CBFalconer Guest

    Joe Estock wrote:
    > Xcott Craver wrote:
    >
    >> The second Underhanded C contest just opened today, and will run
    >> until July 4th. The Prize is a ThinkGeek gift certificate.
    >>
    >> The object is to write deceptive C code, code that does something
    >> malicious but looks innocent and simple enough to pass a cursory
    >> examination of the source.

    >
    > [snip]
    >
    > Does this qualify? :)
    >
    > Hint: this compiles cleanly and runs just fine - just one problem. Can
    > you find out what the problem is without compiling and running it?
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int main(void)
    > {
    > char buffer[600000];
    > char piece[10];
    > long i;
    >
    > strcpy(buffer, "");
    >
    > for(i = 0; i <= 199999; i++)
    > {
    > sprintf(piece, "%ld", i);
    > strcat(buffer, piece);
    > }
    >
    > printf("5=%d\n", strlen(buffer));
    >
    > return(0);
    > }


    Apart from exhibiting undefined behaviour? Even assuming that the
    assignment of storage for buffer works, which is not guaranteed.

    BTW, using strlcat could avert the undefined problem.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
    CBFalconer, Apr 6, 2006
    #9
  10. Xcott Craver

    Richard Bos Guest

    -cnrc.gc.ca (Walter Roberson) wrote:

    > In article <>,
    > Sebastian Gottschalk <> wrote:
    >
    > >With the little correction done, it does the printf 2 times.
    > >But well, compile it with a different endianess and you'll see why the
    > >difference between uint8 and uint32 is an important detail. :)

    >
    > Hmmm, the result would depend on the endianness. Endianness is
    > a property of the processor + operating system combination, not
    > necessarily of the operating system by itself.


    Nothing in C is _necessarily_ a property of the OS itself. One can
    always run any program in a C interpreter which provides identical,
    repeatable behaviour on any OS it runs on.
    More simply, if a certain OS provides default C libraries, and some
    function in those libraries is sub-optimal, there is nothing to forbid
    the implementation (as opposed to the user-programmer!) from redefining
    that function _for that implementation only_.

    Richard
    Richard Bos, Apr 6, 2006
    #10
  11. Xcott Craver

    jaysome Guest

    Richard Bos wrote:

    > -cnrc.gc.ca (Walter Roberson) wrote:
    >
    >
    >>In article <>,
    >>Sebastian Gottschalk <> wrote:
    >>
    >>
    >>>With the little correction done, it does the printf 2 times.
    >>>But well, compile it with a different endianess and you'll see why the
    >>>difference between uint8 and uint32 is an important detail. :)

    >>
    >>Hmmm, the result would depend on the endianness. Endianness is
    >>a property of the processor + operating system combination, not
    >>necessarily of the operating system by itself.

    >
    >
    > Nothing in C is _necessarily_ a property of the OS itself. One can
    > always run any program in a C interpreter which provides identical,
    > repeatable behaviour on any OS it runs on.
    > More simply, if a certain OS provides default C libraries, and some
    > function in those libraries is sub-optimal, there is nothing to forbid
    > the implementation (as opposed to the user-programmer!) from redefining
    > that function _for that implementation only_.


    That's hard to believe. Do you have a section number from the C standard
    that supports your position?

    I can see how an implementation could provide a sub-optimal
    implementation, but I can't see how that implementation could sacrifice
    functionality. Sure, it may be slower, but it should still work as expected.
    jaysome, Apr 6, 2006
    #11
  12. jaysome wrote:
    > Richard Bos wrote:
    >
    >> -cnrc.gc.ca (Walter Roberson) wrote:
    >>
    >>
    >>> In article <>,
    >>> Sebastian Gottschalk <> wrote:
    >>>
    >>>
    >>>> With the little correction done, it does the printf 2 times.
    >>>> But well, compile it with a different endianess and you'll see why the
    >>>> difference between uint8 and uint32 is an important detail. :)
    >>>
    >>> Hmmm, the result would depend on the endianness. Endianness is
    >>> a property of the processor + operating system combination, not
    >>> necessarily of the operating system by itself.

    >>
    >>
    >> Nothing in C is _necessarily_ a property of the OS itself. One can
    >> always run any program in a C interpreter which provides identical,
    >> repeatable behaviour on any OS it runs on.
    >> More simply, if a certain OS provides default C libraries, and some
    >> function in those libraries is sub-optimal, there is nothing to forbid
    >> the implementation (as opposed to the user-programmer!) from redefining
    >> that function _for that implementation only_.

    >
    > That's hard to believe. Do you have a section number from the C standard
    > that supports your position?


    Hm... f.e. fgets() might be a macro. On GLIBC and many other
    implementations it's actually a function and some stupid programs expect
    t to be so, but on dietlibc it's really just a macro.

    > I can see how an implementation could provide a sub-optimal
    > implementation, but I can't see how that implementation could sacrifice
    > functionality. Sure, it may be slower, but it should still work as
    > expected.


    Oh, you don't know about macros? Try to understand how
    max(a,max(b,max(c,max(d,max(e,f))))) expands.
    Sebastian Gottschalk, Apr 6, 2006
    #12
  13. Xcott Craver

    pete Guest

    Sebastian Gottschalk wrote:
    >
    > jaysome wrote:
    > > Richard Bos wrote:
    > >
    > >> -cnrc.gc.ca (Walter Roberson) wrote:
    > >>
    > >>
    > >>> In article <>,
    > >>> Sebastian Gottschalk <> wrote:
    > >>>
    > >>>
    > >>>> With the little correction done, it does the printf 2 times.
    > >>>> But well, compile it with a different endianess and you'll see why the
    > >>>> difference between uint8 and uint32 is an important detail. :)
    > >>>
    > >>> Hmmm, the result would depend on the endianness. Endianness is
    > >>> a property of the processor + operating system combination, not
    > >>> necessarily of the operating system by itself.
    > >>
    > >>
    > >> Nothing in C is _necessarily_ a property of the OS itself. One can
    > >> always run any program in a C interpreter which provides identical,
    > >> repeatable behaviour on any OS it runs on.
    > >> More simply, if a certain OS provides default C libraries, and some
    > >> function in those libraries is sub-optimal, there is nothing to forbid
    > >> the implementation (as opposed to the user-programmer!) from redefining
    > >> that function _for that implementation only_.

    > >
    > > That's hard to believe. Do you have a section number from the C standard
    > > that supports your position?

    >
    > Hm... f.e. fgets() might be a macro.
    > On GLIBC and many other
    > implementations it's actually
    > a function and some stupid programs expect
    > t to be so, but on dietlibc it's really just a macro.


    On a conforming implementation,
    if a standard library function is rendered as a macro
    then there also has to be a function version.
    If <stdio.h> has been #included,
    then you can consider (&fgets) to be a valid expression.

    > > I can see how an implementation could provide a sub-optimal
    > > implementation,
    > > but I can't see how that implementation could sacrifice
    > > functionality. Sure, it may be slower, but it should still work as
    > > expected.

    >
    > Oh, you don't know about macros? Try to understand how
    > max(a,max(b,max(c,max(d,max(e,f))))) expands.


    --
    pete
    pete, Apr 6, 2006
    #13
  14. Xcott Craver

    pemo Guest

    Xcott Craver wrote:
    > The second Underhanded C contest just opened today, and will run until
    > July 4th. The Prize is a ThinkGeek gift certificate.
    >
    > The object is to write deceptive C code, code that does something
    > malicious but looks innocent and simple enough to pass a cursory
    > examination of the source.
    >
    > Last year's contest was to write an image processing routine that
    > covertly embedds fingerprints in the images it creates. This year's
    > challenge is to write C code that runs fine on one OS but mysteriously
    > slowly on a competing OS.



    Some interesting and funny stuff about this on slashdot today ...

    http://it.slashdot.org/article.pl?sid=06/04/05/1255233

    --
    ==============
    Not a pedant
    ==============
    pemo, Apr 6, 2006
    #14
    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. Mel
    Replies:
    4
    Views:
    479
    Jan Faerber
    Nov 23, 2004
  2. shawn modersohn

    SSL + .htaccess / when encryption begins

    shawn modersohn, Mar 28, 2006, in forum: HTML
    Replies:
    1
    Views:
    392
    Benjamin Niemann
    Mar 28, 2006
  3. Xcott Craver

    The 1st Annual Underhanded C Contest

    Xcott Craver, Jun 11, 2005, in forum: C Programming
    Replies:
    2
    Views:
    324
    Xcott Craver
    Jun 11, 2005
  4. codefest
    Replies:
    0
    Views:
    232
    codefest
    Mar 5, 2010
  5. The Underhanded C Contest is back

    , Apr 2, 2013, in forum: C Programming
    Replies:
    2
    Views:
    217
Loading...

Share This Page