How to protect aagainst string variable overwriting another variable?

I am working on a pretty simple program in MS Visual C++ 6.0. Its basically a C program, but I like the IDE of C++. Anyway, I came across a very unexpected bug. I have the following relevant variable:

 double TOT = 100000;
 char out_string[900];

Never in the entire program do I change the value of TOT.
Later in the program, I have a line of code to change the value of out_string and write it to a txt file:


sprintf(out_string,"%11.5d\t%11.5d\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf",f,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m);
outFile0 << out_string <<endl;

I am focusing on this  line because I had a strange bug where TOT was being reset to zero and I isolated this line as the cause by doing the following:

printf("---TOT =  %lf ---1",TOT);
sprintf(out_string,"%11.5d\t%11.5d\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf",f,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m);
outFile0 << out_string <<endl;
printf("---TOT =  %lf ---2",TOT);

and getting the resulting output: ---TOT = 100000 ---1---TOT = 0.0000---2

So it turns out that if I shorten the string or change the definition to

char out_string[1500];

the problem is solved.

But for the future I'd like to know how I can protect against this apparent "overwriting" of the variable TOT.

Can anyone give an explanation of what happened, what I did wrong, why the compiler gave no warnings, and how I can protect against this in the future?

THanks!!

Steve

stevereschAsked:
Who is Participating?
 
stefan73Connect With a Mentor Commented:
Hi steveresch,
> sprintf(out_string,

Never use sprintf, it's prone to buffer overflows. Use snprintf instead:
 int snprintf(char *s,  size_t  n,  const  char  *format,  /* args*/ ...);

So you'd do:
snprintf(out_string,sizeof(out_string),"%11.5d\t%11.5d\t%11.5lf\

Check snprintf's return value:
     The snprintf() function returns  the  number  of  characters
     formatted, that is, the number of characters that would have
     been written to the buffer if it were large enough.  If  the
     value  of  n  is  0  on a call to snprintf(), an unspecified
     value less than 1 is returned.

If it's bigger than your buffer size, you have a problem.

Cheers,
Stefan
0
 
lakshman_ceCommented:
Can you plz tell where is the following code declared?
double TOT = 100000;
char out_string[900];


I have tested the following code
void main()
{

      double TOT = 100000;
       char out_string[900];
      int ,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m
                //not initilized

      printf(out_string,"%11.5d\t%11.5d\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf",f,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m);
      cout << out_string <<endl;

      printf("---TOT =  %lf ---1",TOT);
      printf(out_string,"%11.5d\t%11.5d\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf",f,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m);
      cout << out_string <<endl;
      printf("---TOT =  %lf ---2",TOT);

}
I could see TOT as 10000.000000 in both cases

-Lakshman
0
 
jhshuklaConnect With a Mentor Commented:
I believe the problem is here:
      TOT                  out_string
|--  8bytes  --|-----------------------  900bytes  -----------------------|
when you write to out_string probably you are running out of space and overwriting TOT. check if your output string is more than 900 chars long (return value of sprintf). btw it should overwrite _after_ or beyond the end of outstring but the compiler is allowed to place TOT after out_string which is the likely problem.
when you allocate 1500 bytes you create enough space for the entire string and your problem is solved. if you are not changing TOT throughout the prgm declare it as a const.

also, you can print addrs of TOT & out_string to see if my suggestion about compiler placing TOT after string was correct.

-- jaydutt
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
efnCommented:
As jhshukla wrote, the program probably wrote beyond the bounds of the array.  Neither the compiler nor the run-time system protects you from errors of this kind in C++ (or C), as part of the language's philosophy of being efficient and close to the hardware.  You can protect against it by being aware of it and programming more carefully, or by using an object of a string class instead of a character array.  A string object manages memory for you, so you don't have to worry about problems like this.

--efn
0
 
efnConnect With a Mentor Commented:
Using snprintf is indeed another valid way to protect yourself, if it's available to you.  Unfortunately, it's not in the C++ standard library.  In Visual C++ 6.0, it appears as _snprintf.
0
 
rstaveleyCommented:
> printf(out_string,"%11.5d\t%11.5d\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf\t%11.5lf",f,d,k1d,k2d,k3d,k1m,k2m,k3m,j1d,j2d,j3d,j1m,j2m,j3m,g,w,muT1d,muT2d,muT3d,muT1m,muT2m,muT3m);

use sprintf
0
 
rstaveleyCommented:
...but really you ought to embrace IOStreams instead of all of this C malarky
0
 
stefan73Commented:
rstaveley,
> ...but really you ought to embrace IOStreams instead of all of this C malarky
Good point. Additionally, this lot of identical fields is probably better printed in a loop.

Stefan
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.