CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Array overflow? How can it happen?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ye



Joined: 11 May 2005
Posts: 57
Location: london

View user's profile Send private message

Array overflow? How can it happen?
PostPosted: Thu Oct 27, 2005 5:15 am     Reply with quote

Hi all,

When I was coding my system, I found a pretty strange thing happened. An array initialized as length 5 extended to a length of 10 after some tricks. This was definitely overflow but I couldn't see how it happend and how to avoid it.

Now I put down a similar code that describes the circumstance:

Code:
   char test[5]="abcd";
   char test2[10];
   int i;


   for(i=0;test[i]!='\0';i++)  // Copy the content of test[] to test2[]
      test2[i] = test[i];

   for(i=4;i<10;i++)      // Fill the rest of test2[] with character 'g'
      test2[i] = 'g';

   test2[i] = '\0';       // Finish test2[] by ending with NUL CHARACTER

   for(i=0;test2[i] != '\0';i++)       // Copy the content of test2[] back to test[]
      test[i] = test2[i];

   test[i] = '\0';        // Finish test[] by ending with NUL CHARACTER
 
   // Print the final content of test[] on to Hyperterminal and it's 'abcdggggg'!!!
   // The length's become 10
   fprintf(COM_B,"\nThe test string  = %s\n", test);




By which process has test[] been extended?

This is definitely overflow but I've looked at the SYMBOL file and none of the adjacent variables to test[] have been affected by the overflow.

Please help!
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Thu Oct 27, 2005 5:38 am     Reply with quote

I think this code is the problem:
Code:
for(i=0;test2[i] != '\0';i++)       // Copy the content of test2[] back to test[]
      test[i] = test2[i];

You copy all 10 characters of test2 to test. So I think the compiler will enlarge test to let it fit the 10 characters.

I am not experienced with this so I could be wrong...

Jos
ye



Joined: 11 May 2005
Posts: 57
Location: london

View user's profile Send private message

PostPosted: Thu Oct 27, 2005 6:09 am     Reply with quote

Thanks for replying.

I am pretty sure it's that statement that causes trouble.

However, I would rather the compiler report an error message than ignore this overflow.

Or can there be other causes?
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 27, 2005 6:21 am     Reply with quote

Code:

   char test[5]="abcd";
   char test2[10];
   int i;


   for(i=0;i<sizeof(test);i++)  // Copy the content of test[] to test2[]
   {
      if (test[i] == 0)
        break;
      test2[i] = test[i];
   }

   for(;i<sizeof(test2)-1;i++)      // Fill the rest of test2[] with character 'g'
      test2[i] = 'g';

   test2[i] = '\0';       // Finish test2[] by ending with NUL CHARACTER

/* The next statement can't be done since the size of test is less than the size of test2
   for(i=0;test2[i] != '\0';i++)       // Copy the content of test2[] back to test[]
      test[i] = test2[i];

   test[i] = '\0';        // Finish test[] by ending with NUL CHARACTER
 */
   // Print the final content of test[] on to Hyperterminal and it's 'abcdggggg'!!!
   // The length's become 10
   fprintf(COM_B,"\nThe test string  = %s\n", test);


The error is not a compiler bug but rather lack of experience in programming. The compiler should give an error or warning if you did something like:
Code:
test[34] = 0;

since it knows that it is outside the bounds of the array. However,
Code:

i=34;
test[i] = 0;

will not give an error and you shouldn't expect it to.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

PostPosted: Thu Oct 27, 2005 6:27 am     Reply with quote

Is this code just an experiment? If not, why not use 'strcpy()' in <string.h> to copy one string to another?
ye



Joined: 11 May 2005
Posts: 57
Location: london

View user's profile Send private message

PostPosted: Thu Oct 27, 2005 7:03 am     Reply with quote

Mark wrote:
Code:

   char test[5]="abcd";
   char test2[10];
   int i;


   for(i=0;i<sizeof(test);i++)  // Copy the content of test[] to test2[]
   {
      if (test[i] == 0)
        break;
      test2[i] = test[i];
   }

   for(;i<sizeof(test2)-1;i++)      // Fill the rest of test2[] with character 'g'
      test2[i] = 'g';

   test2[i] = '\0';       // Finish test2[] by ending with NUL CHARACTER

/* The next statement can't be done since the size of test is less than the size of test2
   for(i=0;test2[i] != '\0';i++)       // Copy the content of test2[] back to test[]
      test[i] = test2[i];

   test[i] = '\0';        // Finish test[] by ending with NUL CHARACTER
 */
   // Print the final content of test[] on to Hyperterminal and it's 'abcdggggg'!!!
   // The length's become 10
   fprintf(COM_B,"\nThe test string  = %s\n", test);


The error is not a compiler bug but rather lack of experience in programming. The compiler should give an error or warning if you did something like:
Code:
test[34] = 0;

since it knows that it is outside the bounds of the array. However,
Code:

i=34;
test[i] = 0;

will not give an error and you shouldn't expect it to.


Yes, this is an experiment.

Mark, thanks for the reply. Yes, I am rather lack of experience in programming so I am still a bit confused.



Quote:
/* The next statement can't be done since the size of test is less than the size of test2
for(i=0;test2[i] != '\0';i++) // Copy the content of test2[] back to test[]
test[i] = test2[i];

test[i] = '\0'; // Finish test[] by ending with NUL CHARACTER
*/


1.
Certainly I can't do the statement above here, but this is just an simple model. In the real code, there's no way to foresee whethere the final length of test2[] is bigger than that of test[]. Therefore, I won't get rid of this statement in my code but find some way around it.

2.


Quote:
Code:

i=34;
test[i] = 0;


will not give an error and you shouldn't expect it to.

I don't know why you think it normal and acceptable for the complier not to give an error on this issue but from my point of view, the complier is certainly not clever enough. But I will accept this fact here.

Now I am talking about the array as a string. Then do you not think it strange that when the code tries to poise '\0' to the end of test[] the compiler fails to realize the index for '\0' is beyond the allowed range???
d00dajo



Joined: 20 Jul 2004
Posts: 34

View user's profile Send private message Send e-mail

Windows programming vs Microcontrollers.
PostPosted: Thu Oct 27, 2005 7:32 am     Reply with quote

Quote:

I don't know why you think it normal and acceptable for the complier not to give an error on this issue but from my point of view, the complier is certainly not clever enough. But I will accept this fact here.
Now I am talking about the array as a string. Then do you not think it strange that when the code tries to poise '\0' to the end of test[] the compiler fails to realize the index for '\0' is beyond the allowed range???


You are thinking in a "Windows programmer fashion". In applications on PCs, the memory used - allocated - for a programs variable can be dynamic. That is, the space needed is allocated automatically. This is done automatically in the background by the Operating System.
In a microcontroller you normally dont have a OS in the base (because of the limitations). The rammemory in itself is a linear memoryspace, 0x0000 - 0x????.There is no such thing as a "string" in the memory. A string is mearely a datatype that we normally interpret in a certain way. the '\0' (end of string) is a character saved in the last memory location, which YOUR PROGRAM interprets as "end of string".

The compiler can only make a STATIC assignment of the memory, not dynamically, since it is not running on the uC. (Windows is actually running on the PC so it can determine in run-time the actual size needed for the string. Normally even windowsprogramming requires the programmer to set up the compiler for generating code that requests automatic resizing of strings.)

However, if you write an mini-OS that allocates memory-space dynamically you can "extend" the string. This is with EXTREMELY high probability NOT something you want to do.


Best Regards,

Daniel Johansson,
Sr. Application Engineer, EmpirBus AB
ye



Joined: 11 May 2005
Posts: 57
Location: london

View user's profile Send private message

PostPosted: Thu Oct 27, 2005 8:46 am     Reply with quote

Hi, Daniel, thanks! Smile

So do you mean, when copying test2[] to test[] which is shorter than test2[], the compiler simply lines up the elements of test2[] in a static way at the address of test[] without realizing the initialised length of test[].

This is actually overflow, innit? But why didn't I see the adjacent variables of test[] got corrupted due to overflow?

Please note that in my real code test[] and the adjacent variables from the SYMBOL file are all global variables.


Best Regards
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 27, 2005 9:03 am     Reply with quote

Quote:
I don't know why you think it normal and acceptable for the complier not to give an error on this issue
Cause I am experienced Razz

You as a programmer are responsible for checking the bounds.
Code:

for(i=0;i<sizeof(test)-1;i++) // Copy the content of test2[] back to test[]
{
  if (test2[i] == 0)
    break;
  test[i] = test2[i];
 
}
test[i] = '\0'; // Finish test[] by ending with NUL CHARACTER


Quote:
So do you mean, when copying test2[] to test[] which is shorter than test2[], the compiler simply lines up the elements of test2[] in a static way at the address of test[] without realizing the initialised length of test[].

The compiler does what you tell it to do. So yeah, it keeps on writing and trashes the contents of the variable adjacent to test.

Quote:
This is actually overflow
Yep, but there is nothing checking for the overflow. It is up to you to do that.
Ttelmah
Guest







PostPosted: Thu Oct 27, 2005 9:14 am     Reply with quote

The 'killer' bt of the code, starts here:
Code:

   for(i=4;i<10;i++)      // Fill the rest of test2[] with character 'g'
      test2[i] = 'g';

   test2[i] = '\0';       // Finish test2[] by ending with NUL CHARACTER

'i', will be _10_ when the loop finishes. So the null gets written into address '11'. The string is then oversized, and may indeed never be terminated (if for instance 'i' is in this address, then it'll not be zero on the next test).
Protection of such accesses is a multi stage process. In a PC, not only is memory dynamically allocated from a 'virtual' pool, but there is hardware, which will give an error if you try to access outside the bounds of an allocated area. You can code to do this yourself (for instance):
Code:

int1 mem_error;
int read_array(int * ptr,int addr,int lim) {
    if (addr<lim) then {
        error=false;
        return (*(ptr + addr));
    }
    error=true;
    return(0);
}

If then on the locations where you read from the array, you call this function instead, with the address of the array, the number of the element you want to read, and the number of elements in the arra, you will get back the character in the array, or the 'mem_error' bit will get set if you try to access outside it's size. Now with some careful use of 'sizeof', ad a similar function for the 'write' operations, you could implement basic memory protection. The 'downside', is how much more work is involved. Generally PIC code is built to be small, and for the size of processor involved fairly 'nimble', and this sort of overhead is not really acceptable, so instead it becomes a case of ensuring that where such things might happen, you trap them yourself...

Best Wishes
d00dajo



Joined: 20 Jul 2004
Posts: 34

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 27, 2005 9:18 am     Reply with quote

ye wrote:
Hi, Daniel, thanks! Smile

So do you mean, when copying test2[] to test[] which is shorter than test2[], the compiler simply lines up the elements of test2[] in a static way at the address of test[] without realizing the initialised length of test[].

This is actually overflow, innit? But why didn't I see the adjacent variables of test[] got corrupted due to overflow?

Please note that in my real code test[] and the adjacent variables from the SYMBOL file are all global variables.


Best Regards


Yes! The program will just copy byte for byte into the ram area starting at position 0 of test.

Yes, it is overflow in the sense that you are overwriting other variables that you didnt intend to. The compiler has no idea that you think of the char[5] type as a string. You have declared an array of characters of size 5, nothing more nothing less.

The variables at position char[4]+1 will be overwritten. I GUARANTEE IT! That you didnt see it might be that you DONT have a variable at memory location char[5]+1, I would need to see the symbol list. Maybe you "rewrite" your variables in the rest of your code or something, but they are certainly overwritten!

//Daniel
Guest








PostPosted: Thu Oct 27, 2005 10:26 am     Reply with quote

Many thanks for all of you spam!

I am pretty clear now! Razz
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group