Bug in EWL malloc?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bug in EWL malloc?

Jump to solution
1,270 Views
alexx_88
Contributor III

Hello!

 

I've been working for a few months on a bare-metal Kinetis project, using Processor Expert to provide the HAL. I'm using CW MCU 10.5.

 

What initially appeared to be a bug in my own code (four bytes being assigned random values in the middle of a buffer), actually translated into what looks to me as a bug in the malloc() routine.

 

/* Second: couldn't find a buffer that would fit. attempt to merge two     existing buffers to make do. */       /* nbytes cannot fit into struct m_buff -> size */     if ( MAX_M_BUFF < nbytes ) {         return NULL;     }       p = head;     while ( NULL != p ) {         if ( NO == p->used ) {             struct m_buff* look_ahd = p->lnk;             size_t tot_room = p->size;               while ((NULL != look_ahd) && (NO == look_ahd->used) && (tot_room < nbytes)) {                 tot_room += ((size_t)look_ahd->size + sizeof(struct m_buff));                 look_ahd = look_ahd->lnk;             }               if ( tot_room >= nbytes ) {                 LOCALALLOC(p, nbytes)                 p->lnk = look_ahd;                 p->used = YES;                 p->size = tot_room;                 #if HEAP_GROWS                 if ((look_ahd != NULL) && (look_ahd->lnk == NULL))                     tail = &p->lnk;                                 #endif                   #if defined(_REENTRANT) && _REENTRANT                 __end_critical_region ( malloc_pool_access );                 #endif                 return ((char_t*) p ) + sizeof( struct m_buff );             }         }         p = p->lnk;     }

 

 

Basically, if multiple free buffers are merged to satisfy the need for a bigger buffer, the tail will keep pointing to where an old 'buffer' used to be. The effect of this is that, when a new buffer is allocated using sbrk(),

 

#if HEAP_GROWS     *tail = new_buff;     new_buff->lnk = NULL;     tail = &new_buff->lnk;      #else

 

the instruction at line 2 will write the address of the new buffer right in the middle of a previously allocated area.

 

This is the current sequence of mallocs/free, I will try to narrow it down to a simpler test-case tomorrow:

a = malloc(8);

b = malloc(16);

free(a);

free(b);

a = malloc(1140);

b = malloc(16);

free(a);

free(b);

a = malloc(200);

b = malloc(16);

free(a);

free(b);

a = malloc(8);

b = malloc(16);

free(a);

free(b);

a = malloc(1140);

b = malloc(16); -> This is when 'tail' overwrites bytes in the middle of my buffer.

 

Wondering if this is something that the development team is aware of and if they have a fix.

 

Thanks,

Alex

Labels (1)
Tags (3)
0 Kudos
1 Solution
809 Views
alexx_88
Contributor III

I've managed to fix this by changing:

if ((look_ahd != NULL) && (look_ahd->lnk == NULL))

  tail = &p->lnk;

to

if (look_ahd == NULL)

  tail = &p->lnk;

in alloc.c, line 468.

Basically, the case that was missed was if all the existing buckets were merged into a bigger one. This is covered by testing if 'look_ahd' is NULL, thus meaning that there are no more buckets. If there are (look_ahd != NULL), then there's no point in modifying the 'tail' variable as it already points to the correct bucket.

Alex

View solution in original post

0 Kudos
4 Replies
809 Views
alexx_88
Contributor III

Guys, any opinion on this? Especially from the CW support team.

Cheers,
Alex

0 Kudos
810 Views
alexx_88
Contributor III

I've managed to fix this by changing:

if ((look_ahd != NULL) && (look_ahd->lnk == NULL))

  tail = &p->lnk;

to

if (look_ahd == NULL)

  tail = &p->lnk;

in alloc.c, line 468.

Basically, the case that was missed was if all the existing buckets were merged into a bigger one. This is covered by testing if 'look_ahd' is NULL, thus meaning that there are no more buckets. If there are (look_ahd != NULL), then there's no point in modifying the 'tail' variable as it already points to the correct bucket.

Alex

0 Kudos
809 Views
Carlos_Musich
NXP Employee
NXP Employee

Hi Alex,

Thank you very much for your comments. Just a couple of questions.

Are you using Kinetis? If so, are you using Freescale ARM compiler? or GCC?

Regards,

Carlos

0 Kudos
809 Views
alexx_88
Contributor III

Hi Carlos,

Yes, I am using Kinetis K22F120 and GCC as the compiler. However, given the nature of the problem and the solution I've found, I think the issue is in malloc's handling of merging the free buffers/buckets, as posted above.

Alex

0 Kudos