low-level question

Discussion in 'C Programming' started by jesso, Aug 30, 2005.

  1. jesso

    jesso Guest

    I couldn't get this on a midterm. Darn!

    Anyone want to help?

    1. Why does the following program output a 0?
    2. Explain in detail.
    3. How could you prevent this outcome without changing the code?


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

    int
    main( int argc, char *argv[] )
    {
    int ii = 1;
    char buf[ 4 ];

    strcpy( buf, "AAAA" );

    printf( "%d\n", ii );

    return 0;
    }
    jesso, Aug 30, 2005
    #1
    1. Advertising

  2. jesso

    Lew Pitcher Guest

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    jesso wrote:
    > I couldn't get this on a midterm. Darn!
    >
    > Anyone want to help?
    >
    > 1. Why does the following program output a 0?


    The program does not /necessarily/ output a 0. The program invokes
    undefined behaviour, and /any/ output (or lack of output) is valid.

    > 2. Explain in detail.


    buf is defined as an array of 4 characters (char buf[4];)
    However, the program uses the standard function strcpy() to modify the
    contents of this array. The string given to strcpy() to copy into buf
    consists of 4 characters, /plus/ a string-termination character of \0.

    When strcpy() copies the initialization string into buf, it will copy 4
    characters (which will fit into buf, as buf is defined as a 4 character
    array), and will terminate the copied string with a \0 character. This
    terminating character will not fit within the confines of buf (which is
    already full), and will be written to some other area of memory.

    Assuming specific environmental and compiler characteristics, this \0
    character /may/ be written in such a manner as to overwrite the
    significant bits of the ii variable, setting ii to 0.

    *However*, there is no guarantee that this can happen. It would require
    - - ii to start /immediately/ after buf in memory, and
    - - ii to be stored as a 'little-endian' binary value

    There is no guarantee, from the code and details provided, that the
    compiler will
    - - align ii to a 4-byte boundary,
    - - order ii to /follow/ buf in memory, or
    - - store int values as little-endian binary numbers

    > 3. How could you prevent this outcome without changing the code?


    Don't run the program.

    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int
    > main( int argc, char *argv[] )
    > {
    > int ii = 1;
    > char buf[ 4 ];
    >
    > strcpy( buf, "AAAA" );
    >
    > printf( "%d\n", ii );
    >
    > return 0;
    > }
    >



    - --

    Lew Pitcher, IT Specialist, Enterprise Data Systems
    Enterprise Technology Solutions, TD Bank Financial Group

    (Opinions expressed here are my own, not my employer's)
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.4 (MingW32)

    iD8DBQFDFFRJagVFX4UWr64RAgk8AJ90VvPuywZWEnLXgjgDM0bd/udhRQCgvu3U
    +cNqEFIlcQbqc1J8T1BxITo=
    =Jp1t
    -----END PGP SIGNATURE-----
    Lew Pitcher, Aug 30, 2005
    #2
    1. Advertising

  3. jesso

    Zara Guest

    jesso wrote:
    > char buf[ 4 ];
    >
    > strcpy( buf, "AAAA" );

    Here, you are copying 5 bytes in 4 byte space (remeber the terminating
    null byte). So, you may have *any* unexpected behaviour. For instance,
    printing a zero. But it could have been an expeption, a segment
    violation, or your computer connecting to some web porn site.
    Zara, Aug 30, 2005
    #3
  4. jesso wrote:
    > I couldn't get this on a midterm. Darn!
    >
    > Anyone want to help?
    >
    > 1. Why does the following program output a 0?
    > 2. Explain in detail.
    > 3. How could you prevent this outcome without changing the code?
    >
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int
    > main( int argc, char *argv[] )
    > {
    > int ii = 1;
    > char buf[ 4 ];
    >
    > strcpy( buf, "AAAA" );
    >
    > printf( "%d\n", ii );
    >
    > return 0;
    > }


    It is undefined behavior in C because you are writing past the end of
    an arry ("AAAA" is 5 characters, buf is 4). Since it is undefined
    behavior, anything can happen. There might be certain behaviors that
    are more likely to occur than others due to nuances of your specific
    platform but I can't think of anything plausible that would account for
    the behavior suggested by the question.

    If ii was char then it might be plausible for ii to be located
    immediately following the space allocated for buf in which case the
    '\0' at the end of the string being copied may be written to ii making
    it's value 0. This is still undefined behavior according to the
    Standard though and would be completely implementation dependant.

    Is this for a general C class or a compiler construction/assembly/etc
    class?

    Robert Gamble
    Robert Gamble, Aug 30, 2005
    #4
  5. >I couldn't get this on a midterm. Darn!
    >
    >Anyone want to help?
    >
    >1. Why does the following program output a 0?


    Who says it does? The standard certainly doesn't require it.

    >2. Explain in detail.


    There are no guarantees that if you overflow an array, it will overflow
    into the variable declared immediately after it. (On some linkers,
    it will overflow into the variable *alphabetically* after it, given
    that they're both auto variables in the same function.) There are also
    no guarantees that this code is running on an endian machine.

    >3. How could you prevent this outcome without changing the code?


    Don't run it? Run on a non-endian machine? Kill the author
    of the code?

    >
    >
    >#include <stdio.h>
    >#include <string.h>
    >
    >int
    >main( int argc, char *argv[] )
    >{
    > int ii = 1;
    > char buf[ 4 ];
    >
    > strcpy( buf, "AAAA" );
    >
    > printf( "%d\n", ii );
    >
    > return 0;
    >}
    >
    Gordon Burditt, Aug 30, 2005
    #5
  6. jesso

    jesso Guest

    I had this question years ago on a midterm and just seen it on a job
    posting.

    The company said if you answer the question intelligently then u will
    get an interview.

    I am not applying, but was curious on what the answers were.

    It is undefined behaviour. By saying " Why does the following program
    output a 0?", must be a trick.
    jesso, Aug 30, 2005
    #6
  7. jesso

    jesso Guest

    >From the ad:

    Still I wonder what they are looking for with:
    "How could you prevent this outcome without changing the code?"

    This is an
    "
    ASM/C Developer/Analyst - Linux platform

    Developer/analyst with strong skills in assembler and C on Linux.
    "

    =============

    QUIZ QUESTION:

    If you can answer this question intelligently, you are guaranteed an
    interview (please remember to attach your resume):

    Why does the following program output a 0? Explain in detail. How
    could you prevent this outcome without changing the code?

    #include &lt;stdio.h&gt;
    #include &lt;string.h&gt;
    int main(int argc, char *argv[])
    {
    int i = 1;
    char buf[4];
    strcpy(buf, "AAAA");
    printf("%d\n", i);
    return 0;
    }
    jesso, Aug 30, 2005
    #7
  8. On 30 Aug 2005 06:46:57 -0700, in comp.lang.c , "jesso"
    <> wrote:

    > Why does the following program output a 0?


    Because of how that particular compiler or OS or hardware implements
    undefined behaviour, vis writing off the end of an array.

    >Explain in detail.


    This isn't a C question, its a hardware / OS / compiler question.

    >How could you prevent this outcome without changing the code?


    Run on different hw/sw which handles the UB differently.
    Compile with special "don't allow UB" options.
    Don't run the app at all - it has a serious bug.

    --
    Mark McIntyre
    CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

    ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
    Mark McIntyre, Aug 30, 2005
    #8
  9. jesso wrote:
    > I couldn't get this on a midterm. Darn!
    >
    > Anyone want to help?
    >
    > 1. Why does the following program output a 0?


    It is an accident. It could return anything. Buffer overflows don't
    result in well-defined behavior.

    > 2. Explain in detail.


    See above.

    > 3. How could you prevent this outcome without changing the code?


    You can't fix code without changing it. What are you smoking? A
    minimum change to the code (not allowed by the conditions) is to declare
    char buf[5]; /* Those spaces around '4' seem to be a clue. */

    [broken code follows]


    > #include <stdio.h>
    > #include <string.h>
    >
    > int
    > main( int argc, char *argv[] )
    > {
    > int ii = 1;
    > char buf[ 4 ];
    >
    > strcpy( buf, "AAAA" );
    >
    > printf( "%d\n", ii );
    >
    > return 0;
    > }
    >
    Martin Ambuhl, Aug 30, 2005
    #9
  10. jesso

    tedu Guest

    jesso wrote:

    > 3. How could you prevent this outcome without changing the code?


    compile with -Dii="a = 1, b"
    tedu, Aug 30, 2005
    #10
  11. jesso

    Bryan Donlan Guest

    jesso wrote:

    > I couldn't get this on a midterm. Darn!
    >
    > Anyone want to help?
    >
    > 1. Why does the following program output a 0?


    Undefined behavior. strcpy writes five characters into a four-character
    buffer ('A'x4, then a 0). Of course, it might not produce a zero. It might
    produce a 1, 42, -999, 'ducks? thanks', erase your harddrive, or simply
    crash.

    In fact, on my system it produces a one with -O1 or higher, so the question
    truly is nonsensical.

    > 2. Explain in detail.
    > 3. How could you prevent this outcome without changing the code?


    You can't. With the code as is, it will always invoke undefined behavior. No
    wonder you couldn't get this on your midterm; it asks the impossible.

    >
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int
    > main( int argc, char *argv[] )
    > {
    > int ii = 1;
    > char buf[ 4 ];

    Make this: char buf[5];
    >
    > strcpy( buf, "AAAA" );

    Or make the string three characters or less.

    >
    > printf( "%d\n", ii );
    >
    > return 0;
    > }


    --
    λz.λi.i(i((λn.λm.λz.λi.nz(λq.mqi))((λn.λz.λi.n(nzi)i)(λz.λi.i(((λn.λz.λi.n
    (nzi)i)(λz.λi.i(iz)))zi)))((λn.λz.λi.n(nzi)i)(λz.λi.i(iz)))zi))
    Bryan Donlan, Aug 30, 2005
    #11
  12. "Robert Gamble" <> writes:
    > jesso wrote:
    >> I couldn't get this on a midterm. Darn!
    >>
    >> Anyone want to help?
    >>
    >> 1. Why does the following program output a 0?
    >> 2. Explain in detail.
    >> 3. How could you prevent this outcome without changing the code?
    >>
    >>
    >> #include <stdio.h>
    >> #include <string.h>
    >>
    >> int
    >> main( int argc, char *argv[] )
    >> {
    >> int ii = 1;
    >> char buf[ 4 ];
    >>
    >> strcpy( buf, "AAAA" );
    >>
    >> printf( "%d\n", ii );
    >>
    >> return 0;
    >> }

    >
    > It is undefined behavior in C because you are writing past the end of
    > an arry ("AAAA" is 5 characters, buf is 4). Since it is undefined
    > behavior, anything can happen. There might be certain behaviors that
    > are more likely to occur than others due to nuances of your specific
    > platform but I can't think of anything plausible that would account for
    > the behavior suggested by the question.


    If ii is allocated just after the end of buf, and if the platform uses
    a little-endian representation for int, the '\0' of "AAAA" could
    plausibly be written over the low-order byte of ii, causing it to be
    set to 0.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Aug 30, 2005
    #12
  13. jesso

    Bryan Donlan Guest

    tedu wrote:

    > jesso wrote:
    >
    >> 3. How could you prevent this outcome without changing the code?

    >
    > compile with -Dii="a = 1, b"


    It's still undefined behavior, and can do whatever it wants.

    --
    λz.λi.i(i((λn.λm.λz.λi.nz(λq.mqi))((λn.λz.λi.n(nzi)i)(λz.λi.i(((λn.λz.λi.n
    (nzi)i)(λz.λi.i(iz)))zi)))((λn.λz.λi.n(nzi)i)(λz.λi.i(iz)))zi))
    Bryan Donlan, Aug 30, 2005
    #13
  14. Keith Thompson wrote:
    > "Robert Gamble" <> writes:
    > > jesso wrote:
    > >> I couldn't get this on a midterm. Darn!
    > >>
    > >> Anyone want to help?
    > >>
    > >> 1. Why does the following program output a 0?
    > >> 2. Explain in detail.
    > >> 3. How could you prevent this outcome without changing the code?
    > >>
    > >>
    > >> #include <stdio.h>
    > >> #include <string.h>
    > >>
    > >> int
    > >> main( int argc, char *argv[] )
    > >> {
    > >> int ii = 1;
    > >> char buf[ 4 ];
    > >>
    > >> strcpy( buf, "AAAA" );
    > >>
    > >> printf( "%d\n", ii );
    > >>
    > >> return 0;
    > >> }

    > >
    > > It is undefined behavior in C because you are writing past the end of
    > > an arry ("AAAA" is 5 characters, buf is 4). Since it is undefined
    > > behavior, anything can happen. There might be certain behaviors that
    > > are more likely to occur than others due to nuances of your specific
    > > platform but I can't think of anything plausible that would account for
    > > the behavior suggested by the question.

    >
    > If ii is allocated just after the end of buf, and if the platform uses
    > a little-endian representation for int, the '\0' of "AAAA" could
    > plausibly be written over the low-order byte of ii, causing it to be
    > set to 0.


    Yep, I was being a little bit narrow-minded when I posted that. I
    realized this shortly after I posted and then saw that Lew Pitcher
    covered this case so I didn't feel the need to amend my post.

    Robert Gamble
    Robert Gamble, Aug 30, 2005
    #14
  15. Groovy hepcat jesso was jivin' on 30 Aug 2005 05:30:18 -0700 in
    comp.lang.c.
    low-level question's a cool scene! Dig it!

    >I couldn't get this on a midterm. Darn!


    Sure. And it's not your homework you want us to do for you, or
    anything.

    >Anyone want to help?
    >
    >1. Why does the following program output a 0?


    For the same reason it might make the computer reach out and smack
    you at any time.

    >2. Explain in detail.


    When you invoke undefined behaviour, anything is allowed to happen.
    This includes the incredibly mundane, such as outputting 0, and the
    downright bizzarre, like making the computer reach out and slap you.

    >3. How could you prevent this outcome without changing the code?


    Don't run the compiled program.

    [Snip code invoking undefined behaviour.]

    --

    Dig the even newer still, yet more improved, sig!

    http://alphalink.com.au/~phaywood/
    "Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
    I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
    Peter Shaggy Haywood, Aug 31, 2005
    #15
  16. Bryan Donlan wrote:
    > tedu wrote:
    >
    >
    >>jesso wrote:
    >>
    >>
    >>>3. How could you prevent this outcome without changing the code?

    >>
    >>compile with -Dii="a = 1, b"

    >
    >
    > It's still undefined behavior, and can do whatever it wants.


    Then how about this:
    compile with -D"strcpy(a,b)"="ii"

    PS
    I would have suggested this: -D"strcpy(a,b)"="strncpy((a),(b),sizeof(b))"
    but that give problems with string.h, which can be avoided by doing the
    following:
    touch string.h
    touch stdio.h
    gcc -nostdinc -isystem . -D"strcpy(a,b)"="strncpy((a),(b),sizeof(a))" \
    -save-temps -o test test.c
    but this is way to compiler and OS specific for the clc newsgroup :)

    Kind regards,
    Johan

    --
    o o o o o o o . . . _____J_o_h_a_n___B_o_r_k_h_u_i_s___
    o _____ || http://www.borkhuis.com |
    .][__n_n_|DD[ ====_____ | |
    >(________|__|_[_________]_|________________________________|

    _/oo OOOOO oo` ooo ooo 'o!o!o o!o!o`
    == VxWorks FAQ: http://www.xs4all.nl/~borkhuis/vxworks/vxworks.html ==
    Johan Borkhuis, Aug 31, 2005
    #16
  17. jesso

    doodoosy Guest

    >3. How could you prevent this outcome without changing the code?

    Plug off your monitor
    doodoosy, Sep 4, 2005
    #17
  18. jesso

    Randy Howard Guest

    jesso wrote
    (in article
    <>):

    > I couldn't get this on a midterm. Darn!
    >
    > Anyone want to help?
    >
    > 1. Why does the following program output a 0?


    Your professor needs to be fired.

    > 2. Explain in detail.


    Reading through the various responses already posted should be
    more than enough ammunition to back up my assertion above.
    If you got this question 'wrong' on your midterm, you should be
    able to make the claim that the question was bogus and
    completely inappropriate, especially the first question about
    the output being 0 for such an exam, not to mention the
    ludicrous notion that it can be fixed without changing the code.


    --
    Randy Howard (2reply remove FOOBAR)
    Randy Howard, Sep 6, 2005
    #18
    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.

Share This Page