strncpy() and null terminated strings

B

Barry

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,&buf[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
 
S

Severian

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.

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.

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.
 
R

Richard Bos

Severian said:
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.)

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
 
D

Dan Pop

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

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
 
M

Malcolm

Severian said:
It was luck that it ever worked.
Bad luck. Seemingly correct behaviour is the most dangerous type of
undefined behaviour, as the Op's experience shows.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top