strncpy() and null terminated strings

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Barry

    strncpy() and null terminated strings

    Hi all! I support a rather large production EDI application with a
    number of C programs, and I ran across a very interesting problem. I
    have some code that used to work just fine for years, and now all of a
    sudden it doesn't work any more. The input to the program did not
    change at all (even ran it through a binary browser to make certain
    there were no hidden chars or something strange) and the program has
    not been recompiled in years.

    In general, I know how to fix the problem but management here wants an
    explanation as to why it ever worked to begin with. So I guess what
    I'm looking for is some theories regarding what may have changed (OS,
    memory configuration, etc.)

    Here's the situation...

    The program is reading a buffer that contains a string value. There
    are no nulls in the string contained in the buffer (if that matters).
    A strncpy() is being used to move substrings from the buffer into
    variables, and then the variables are written to a report using
    fprintf(). THE PROBLEM IS THAT THE STRINGS ARE NOT NULL TERMINATED
    (and also not initialized with any values if that makes a difference
    to you). Like I said earlier, this worked for years but all of a
    sudden garbage is being outputted to the report unless I change the
    program to null terminate the strings.

    So I'm looking for theories as to why this ever worked to begin with
    (actually that is what management here wants to know, and I'm having
    trouble providing them with an explanation). Somehow these variables
    must have been initialized with null values (or something like that)
    and now they are not - so what could have changed to cause a
    difference?

    Here are some snippets of code from the program if it helps (I didn't
    write this, I only keep it working):

    ....
    <some code>
    ....

    /* Global declaration */
    struct FA_Table {
    char CUST_ID[5];
    char CUST_NAME[37];
    char GS03[16];
    char ISA05[3];
    char GS02[16];
    char newline;
    };

    ....
    <some code>
    ....

    int Process_msga( fa, in, out)
    register struct FuncAck *fa;
    FILE **in, **out;
    {
    char TERM[3];
    struct FuncAck tbl;

    while ( fgets(buf, 256, *in ) != (char *)NULL )
    {

    if ( strncmp(buf, "ISA", 3)==0 ) {
    TERM[0] = buf[3],
    TERM[1] = '\n';
    TERM[2] = '\0';

    /* Below is the problem */
    strncpy(fa->isa.ISA05,&b uf[32],2);
    /*Adding fa->isa.ISA05[2]=0; here makes everything work ok*/
    printf("found ISA05|%s|\n",fa->isa.ISA05);

    ....
    <more code>
    ....
    }


    The printf above outputs the string + garbage unless I null terminate
    the string. So any ideas why it ever worked to begin with???

    Barry
  • Severian

    #2
    Re: strncpy() and null terminated strings

    On 8 Apr 2004 06:39:05 -0700, barry26@bellsou th.net (Barry) wrote:
    [color=blue]
    >Hi all! I support a rather large production EDI application with a
    >number of C programs, and I ran across a very interesting problem. I
    >have some code that used to work just fine for years, and now all of a
    >sudden it doesn't work any more. The input to the program did not
    >change at all (even ran it through a binary browser to make certain
    >there were no hidden chars or something strange) and the program has
    >not been recompiled in years.[/color]

    <snip>
    [color=blue]
    >The program is reading a buffer that contains a string value. There
    >are no nulls in the string contained in the buffer (if that matters).
    >A strncpy() is being used to move substrings from the buffer into
    >variables, and then the variables are written to a report using
    >fprintf(). THE PROBLEM IS THAT THE STRINGS ARE NOT NULL TERMINATED
    >(and also not initialized with any values if that makes a difference
    >to you). Like I said earlier, this worked for years but all of a
    >sudden garbage is being outputted to the report unless I change the
    >program to null terminate the strings.[/color]

    Some change in the execution environment, or a change in activity of
    the program prior to the call, has made the memory used for automatic
    allocation of your structure contain something other than zeros. (This
    would be the stack on most common desktop and server platforms.)

    It was luck that it ever worked.

    --
    Sev

    Comment

    • Richard Bos

      #3
      Re: strncpy() and null terminated strings

      Severian <severian@chlam ydia-is-not-a-flower.com> wrote:
      [color=blue]
      > Some change in the execution environment, or a change in activity of
      > the program prior to the call, has made the memory used for automatic
      > allocation of your structure contain something other than zeros. (This
      > would be the stack on most common desktop and server platforms.)[/color]

      And just one example of how this _could_ come to pass: maybe your
      application has been collecting data all these years, and this data has
      finally grown so large that, in the course of the calculations, that
      part of memory, which previously used to be newly allocated, now needs
      to come from used and reclaimed memory blocks.

      Richard

      Comment

      • Dan Pop

        #4
        Re: strncpy() and null terminated strings

        In <254a10f7.04040 80539.bd272e1@p osting.google.c om> barry26@bellsou th.net (Barry) writes:
        [color=blue]
        >The printf above outputs the string + garbage unless I null terminate
        >the string. So any ideas why it ever worked to begin with???[/color]

        Yes: the structure was initialised, by default and by accident with all
        zeros. These zeros acted as string terminators. At some point, the
        structure was no longer initialised with zeros, but with garbage. Now,
        your "strings" were no longer null terminated and printf had no good
        reason to stop at the intended place. The reason of the change is
        external to the program (e.g. the new libraries coming with a new version
        of the OS) and code that accidentally worked before no longer worked
        after.

        The easiest fix is to explicitly nullify all your data containers
        (arrays, buffers, structures) before starting to fill them with
        input data. Code that worked previously by accident will work now by
        design, if you leave at least one byte untouched when storing the data
        in your containers.

        If the code wasn't supposed to handle strings, it should have used memcpy
        instead of strncpy and *all* the %s conversion specifications should have
        contained an explicit precision specification, i.e. %.2s for a data field
        that is no longer than 2 characters.

        Dan
        --
        Dan Pop
        DESY Zeuthen, RZ group
        Email: Dan.Pop@ifh.de

        Comment

        • Malcolm

          #5
          Re: strncpy() and null terminated strings


          "Severian" <severian@chlam ydia-is-not-a-flower.com> wrote in[color=blue]
          >
          > It was luck that it ever worked.
          >[/color]
          Bad luck. Seemingly correct behaviour is the most dangerous type of
          undefined behaviour, as the Op's experience shows.


          Comment

          Working...