[En-Nut-Discussion] r6796 introduced possible memory leak in os/timer.c

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Sat Jan 16 19:54:42 CET 2021


Philipp Burch writes:
> Hi everyone,
> 
> I work with the devnut_tiva branch of Ethernut which I update 
> irregularly with the changes from trunk. Since such a merge in last 
> september, I started to experience spurious memory leaks in one of our 
> applications. The symptom is that the available heap memory continuously 
> decreased, sometimes faster, sometimes slower, until the whole 
> application finally crashed. Since our software changed a lot in the 
> meantime, I first searched there for the reason, but without success. So 
> I finally reverted the Ethernut sources back to before the merge (to 
> r6786, almost two years back) and the issue was gone.
> 
> While running through all the changes introduced between r6786 and 
> r6912, the following change of r6796 in os/timer.c caught my attention:
> 
> -            if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
> -                NutHeapFree(tn);
> -            }
> -            else {
> +            tn->tn_ticks_left = tn->tn_ticks;
> +            if (tn->tn_ticks_left == 0) {
> +                if (!(tn->tn_flags & TM_HAS_OWN_STRUCT)) {
> +                    NutHeapFree(tn);
> +                }
> +            } else {
> 
> Reverting just this change (by commenting out the check for 
> TM_HAS_OWN_STRUCT) also fixed the behaviour. But the change as such is 
> fine and not the actual error.
> 
> The error is in NutTimerCreate(), a few lines further down:
> 
> static NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) 
> (HANDLE, void *), void *arg, uint8_t flags)
> {
>      NUTTIMERINFO *tn;
> 
>      tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
>      if (tn) {
>          tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
> 
>          /*
>           * Periodic timers will reload the tick counter on each timer
>           * intervall.
>           */
>          if (flags & TM_ONESHOT) {
>              tn->tn_ticks = 0;
>          } else {
>              tn->tn_ticks = ticks;
>          }
> 
>          /* Set callback and callback argument. */
>          tn->tn_callback = callback;
>          tn->tn_arg = arg;
>      }
>      return tn;
> }
> 
> The function checks the passed flags argument, but fails to write it 
> into the newly created tn->tn_flags. This means that the tn_flags field 
> stays uninitialized and whatever the memory contents were before being 
> allocated with NutHeapAlloc() is now set for this field. So if, by 
> coincidence, the memory contained 0x80000000, the timer will have 
> TM_HAS_OWN_STRUCT set, causing the memory leak because the structure 
> will not be freed when it expires.
> 
> The fix is trivial:
> 
> --- nut/os/timer.c	(revision 6917)
> +++ nut/os/timer.c	(working copy)
> @@ -641,6 +641,7 @@
>           /* Set callback and callback argument. */
>           tn->tn_callback = callback;
>           tn->tn_arg = arg;
> +        tn->tn_flags = flags;
>       }
>       return tn;
>   }
> 
> I committed it as r6918, but only for the devnut_tiva branch; I think I 
> don't even have permission to commit to trunk. I assume that it is a 
> good idea to use the flags given to NutTimerCreate() to avoid confusion, 
> but it would be just as fine to properly initialize tn_flags to zero.
>

Just a short comment: I feel uneager at all that  run-time allocation/ deallocation  happens at all.
 
-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------


More information about the En-Nut-Discussion mailing list