Tuesday, October 11, 2005

An instance of memory corruption in a structure

Today i was working on a structure that looked like this

struct a_{
U8bit i;
U8bit data[0];
};
typedef a_ a_t;

As can be seen the 'data' is an expandable array. This was used to point to another structure say b_t;

typedef struct b_{
int integer;
}b_t;

a_t *a;
b_t *b; // another structure of arbitrary type
memcpy(a->data, b, sizeof(b));

Assume that the memory location of structure 'a' is 200 and that of 'b' is '210'. Now since the first element of 'a' is of size 1 byte, the statement memcpy(a->data, b, sizeof(b)); had copied the structure 'b' to the memry location 201. Everything seemed to go well till now. but when i tried to unpack the intger of 'b' structure from 'a' structure I got a Segmentation Fault. (OS: Solaris ). This is because i was trying to read the integer from an memory location that was not a muliple of 4. Purify categorises this as Misaligned Memory Read.

With the knowledge i have today, this can be avoided in two ways.
1. The structure declaration of a_t shud be like this
struct a_
{
U8bit data[0];
U8bit i;
};
The parameter 'i' has been moved down to prevent misalignment of the structure to be packed into 'data' field

2. Using memcpy.

Say we wanna use this statement..

int temp = (b_t *)(a->data)->integer;

This will result in a Segmentation fault. Instead use a temporary struture of type b_t, memcpy a->data into it and then use it.

b_t *temp_struct;
temp_struct = (b_t *)malloc(sizeof(b_t)); // This structure will be properly alligned
memcpy(temp_struct, a->data, sizeof(b_t));

temp = temp_struct->integer.

This wud do the trick .

Sometimes (as was the case with me), the solution 1 wont be plausible. In my case, I dint want the structure definition to change.

0 Comments:

Post a Comment

<< Home