From 8a2a5015e6e9aaf64dc35f32495e28cf4aa88a89 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Mon, 3 Jul 2023 16:35:40 +0200
Subject: [PATCH] T tracer tools: fix memory leaks, clang warnings

- Fix memory leaks detected by ASan
- Initialize variables that are flagged by compiler
- C struct initializer: x:y needs to be .x=y
---
 common/utils/T/check_vcd.c        |  2 ++
 common/utils/T/tracer/database.c  | 52 ++++++++++++++++++++++++++-----
 common/utils/T/tracer/database.h  |  1 +
 common/utils/T/tracer/extract.c   |  4 +--
 common/utils/T/tracer/gui/event.c |  2 +-
 common/utils/T/tracer/textlog.c   |  2 +-
 6 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/common/utils/T/check_vcd.c b/common/utils/T/check_vcd.c
index 6e415c2d94..d946834270 100644
--- a/common/utils/T/check_vcd.c
+++ b/common/utils/T/check_vcd.c
@@ -256,7 +256,9 @@ int main(int argc, char *argv[])
       err("%s is not correct in T_messages.txt", name);
     i++;
   }
+  free(l);
   fclose(in);
+  free_database(database);
   if (i != last_fun + 1) err("VCD FUNCTIONS wrong in T_messages.txt");
 
   return 0;
diff --git a/common/utils/T/tracer/database.c b/common/utils/T/tracer/database.c
index 543ab66664..347ca7cfcf 100644
--- a/common/utils/T/tracer/database.c
+++ b/common/utils/T/tracer/database.c
@@ -43,6 +43,14 @@ typedef struct {
   buffer value;
 } parser;
 
+void *my_bsearch(const void *key, const void *base,
+                 size_t nmemb, size_t size,
+                 int (*compar)(const void *, const void *))
+{
+  if (nmemb == 0) return NULL;
+  return bsearch(key, base, nmemb, size, compar);
+}
+
 void put(buffer *b, int c)
 {
   if (b->size == b->maxsize) {
@@ -125,7 +133,7 @@ int string_cmp(const void *_p1, const void *_p2)
 
 id *add_id(database *r, char *idname, int i)
 {
-  if (bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
+  if (my_bsearch(&(id){.name=idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
     { printf("ERROR: ID '%s' declared more than once\n", idname); exit(1); }
   if ((r->isize & 1023) == 0) {
     r->i = realloc(r->i, (r->isize + 1024) * sizeof(id));
@@ -143,14 +151,14 @@ id *add_id(database *r, char *idname, int i)
   r->i[r->isize].id = i;
   r->isize++;
   qsort(r->i, r->isize, sizeof(id), id_cmp);
-  return (id*)bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp);
+  return (id*)my_bsearch(&(id){.name=idname}, r->i, r->isize, sizeof(id), id_cmp);
 }
 
 group *get_group(database *r, char *group_name)
 {
   group *ret;
 
-  ret = bsearch(&(group){name:group_name},
+  ret = my_bsearch(&(group){.name=group_name},
                 r->g, r->gsize, sizeof(group), group_cmp);
   if (ret != NULL) return ret;
 
@@ -166,7 +174,7 @@ group *get_group(database *r, char *group_name)
 
   qsort(r->g, r->gsize, sizeof(group), group_cmp);
 
-  return bsearch(&(group){name:group_name},
+  return my_bsearch(&(group){.name=group_name},
                  r->g, r->gsize, sizeof(group), group_cmp);
 }
 
@@ -182,7 +190,7 @@ void group_add_id(group *g, char *id)
 
 void id_add_group(id *i, char *group)
 {
-  char *g = bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
+  char *g = my_bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
   if (g != NULL) return;
 
   if ((i->gsize & 1023) == 0) {
@@ -392,7 +400,7 @@ void list_groups(void *_d)
 static int onoff_id(database *d, char *name, int *a, int onoff)
 {
   id *i;
-  i = bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
+  i = my_bsearch(&(id){.name=name}, d->i, d->isize, sizeof(id), id_cmp);
   if (i == NULL) return 0;
   a[i->id] = onoff;
   printf("turning %s %s\n", onoff ? "ON" : "OFF", name);
@@ -403,7 +411,7 @@ static int onoff_group(database *d, char *name, int *a, int onoff)
 {
   group *g;
   int i;
-  g = bsearch(&(group){name:name}, d->g, d->gsize, sizeof(group), group_cmp);
+  g = my_bsearch(&(group){.name=name}, d->g, d->gsize, sizeof(group), group_cmp);
   if (g == NULL) return 0;
   for (i = 0; i < g->size; i++) onoff_id(d, g->ids[i], a, onoff);
   return 1;
@@ -442,7 +450,7 @@ char *event_vcd_name_from_id(void *_database, int id)
 int event_id_from_name(void *_database, char *name)
 {
   database *d = _database;
-  id *i = (id*)bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
+  id *i = (id*)my_bsearch(&(id){.name=name}, d->i, d->isize, sizeof(id), id_cmp);
   if (i == NULL)
     { printf("%s:%d: '%s' not found\n", __FILE__, __LINE__, name); abort(); }
   return i->id;
@@ -516,3 +524,31 @@ void database_get_generic_description(void *_d, int id,
   PUTC(&o, 0);
   *desc = o.obuf;
 }
+
+void free_database(void *_d)
+{
+  database *d = _d;
+  int i;
+  int j;
+  free(d->name);
+  for (i = 0; i < d->isize; i++) {
+    free(d->i[i].name);
+    free(d->i[i].desc);
+    free(d->i[i].groups);
+    for (j = 0; j < d->i[i].asize; j++) {
+      free(d->i[i].arg_type[j]);
+      free(d->i[i].arg_name[j]);
+    }
+    free(d->i[i].arg_type);
+    free(d->i[i].arg_name);
+    free(d->i[i].vcd_name);
+  }
+  free(d->i);
+  for (i = 0; i < d->gsize; i++) {
+    free(d->g[i].name);
+    free(d->g[i].ids);
+  }
+  free(d->g);
+  free(d->id_to_pos);
+  free(d);
+}
diff --git a/common/utils/T/tracer/database.h b/common/utils/T/tracer/database.h
index 9fdbaed7c6..ee126ca145 100644
--- a/common/utils/T/tracer/database.h
+++ b/common/utils/T/tracer/database.h
@@ -3,6 +3,7 @@
 
 /* returns an opaque pointer - truly a 'database *', see database.c */
 void *parse_database(char *filename);
+void free_database(void *database);
 void dump_database(void *database);
 void list_ids(void *database);
 void list_groups(void *database);
diff --git a/common/utils/T/tracer/extract.c b/common/utils/T/tracer/extract.c
index d66e8a3bb8..bd1649a31a 100644
--- a/common/utils/T/tracer/extract.c
+++ b/common/utils/T/tracer/extract.c
@@ -55,8 +55,8 @@ int main(int n, char **v)
   int found;
   int count = 1;
   int check_time = 0;
-  time_t sec;
-  long nsec;
+  time_t sec = 0;  /* initialization not necessary but gcc is not happy */
+  long nsec = 0;   /* initialization not necessary but gcc is not happy */
 
   for (i = 1; i < n; i++) {
     if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
diff --git a/common/utils/T/tracer/gui/event.c b/common/utils/T/tracer/gui/event.c
index 842318fcea..862f4d67dd 100644
--- a/common/utils/T/tracer/gui/event.c
+++ b/common/utils/T/tracer/gui/event.c
@@ -107,7 +107,7 @@ void send_event(gui *_gui, enum event_type type, ...)
   struct gui *g = _gui;
   int do_write = 0;
   va_list ap;
-  struct event *e;
+  struct event *e = NULL;  /* initialization not necessary but gcc is not happy */
 
   if (g->queued_events == NULL) do_write = 1;
 
diff --git a/common/utils/T/tracer/textlog.c b/common/utils/T/tracer/textlog.c
index f83cc7efd3..99cddaf43a 100644
--- a/common/utils/T/tracer/textlog.c
+++ b/common/utils/T/tracer/textlog.c
@@ -86,7 +86,7 @@ int main(int n, char **v)
   int i;
   event_handler *h;
   logger *textlog;
-  gui *g;
+  gui *g = NULL;    /* initialization not necessary but gcc is not happy */
   int gui_mode = 0;
   view *out;
   int gui_active = 1;
-- 
2.26.2