From 6b3cc76e323080999a870480d2e4ce384da47ac8 Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:22:14 +0000 Subject: [PATCH 1/6] Fixed a memory leak in the uio_find_devices() function --- base.c | 23 +++++++++++++++++++++-- configure.ac | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/base.c b/base.c index 95b77db..282bf58 100644 --- a/base.c +++ b/base.c @@ -22,6 +22,7 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include #include #include #include @@ -206,6 +207,7 @@ struct uio_info_t **uio_find_devices () int i, t = 0, nr; snprintf (sysfsname, sizeof (sysfsname), "%s/class/uio", sysfs); + /* This includes the two directories . and .. */ nr = scandir (sysfsname, &namelist, 0, alphasort); if (nr < 0) { @@ -216,7 +218,6 @@ struct uio_info_t **uio_find_devices () info = calloc (nr, sizeof (struct uio_info_t *)); if (!info) { - errno = ENOMEM; g_warning (_("calloc: %s\n"), g_strerror (errno)); goto out; } @@ -229,6 +230,12 @@ struct uio_info_t **uio_find_devices () info [t++] = create_uio_info (sysfsname, namelist [i]->d_name); } + /* + * Because . and .. should have been in the original result which was + * used to calculate the length to allocate, we are guaranteed that the + * array will be NULL terminated. + */ + assert(info[nr] == NULL); out: for (i = 0; i < nr; i++) @@ -255,17 +262,29 @@ struct uio_info_t *uio_find_by_uio_name (char *uio_name) if (!uio_list) return NULL; + /* + * Iterating over the elements returned from uio_find_devices() assumes + * that either a match is found or the NULL sentinel is reached. + */ for (list = uio_list; *list; list++) { struct uio_info_t *candidate = *list; name = uio_get_name (candidate); + /* + * Free every entry in the result from uio_find_devices() except + * the one that matches + */ if (!strcmp (name, uio_name)) { info = candidate; - break; + } else { + free(candidate); } } + /* If we found a match, all but the matching one should be freed. If no + * match, then the entire result should be freed. In either case, we can + * free the result from uio_find_devices() */ free (uio_list); return info; diff --git a/configure.ac b/configure.ac index 101abd3..0c72312 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Every other copy of the package version number gets its value from here -AC_INIT(libuio, 0.2.8, https://github.com/linutronix/libuio/issues) +AC_INIT(libuio, 0.3.0, https://github.com/missinglinkelectronics/libuio/issues) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) From 9bf2f19b809eb366723f91c3b62723b22cd85be2 Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:54:20 +0000 Subject: [PATCH 2/6] Needed to use the `uio_free_info()` helper function --- base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base.c b/base.c index 282bf58..82a191e 100644 --- a/base.c +++ b/base.c @@ -279,7 +279,7 @@ struct uio_info_t *uio_find_by_uio_name (char *uio_name) if (!strcmp (name, uio_name)) { info = candidate; } else { - free(candidate); + uio_free_info(candidate); } } /* If we found a match, all but the matching one should be freed. If no From 2729c570fa147fdf88f230192aa711e46daf5a9f Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:55:06 +0000 Subject: [PATCH 3/6] Inserted an error report to be consistent with the rest of the library --- helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/helper.c b/helper.c index 91c076b..809d6f5 100644 --- a/helper.c +++ b/helper.c @@ -293,8 +293,10 @@ struct uio_info_t *create_uio_info (char *dir, char *name) char filename [PATH_MAX]; info = calloc (1, sizeof (struct uio_info_t)); - if (!info) + if (!info) { + g_warning (_("calloc: %s\n"), g_strerror (errno)); return NULL; + } snprintf (filename, PATH_MAX, "%s/%s", dir, name); info->path = strdup (filename); From 08ac9c51306f9d8552db734d3f12af2e40228ee4 Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:21:22 +0000 Subject: [PATCH 4/6] Fixed the last freeing of resources and added a missing function declaration. --- base.c | 12 +++++++++--- libuio.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/base.c b/base.c index 82a191e..00676d6 100644 --- a/base.c +++ b/base.c @@ -187,8 +187,14 @@ void uio_free_info(struct uio_info_t* info) free (info->name); if (info->version) free (info->version); - if (info->maps) - free (info->maps); + if (info->maps) { + for (int i = 0; i < info->maxmap; i++) { + if (info->maps[i].name) { + free(info->maps[i].name); + } + } + free(info->maps); + } if (info->devname) free (info->devname); free (info); @@ -235,7 +241,7 @@ struct uio_info_t **uio_find_devices () * used to calculate the length to allocate, we are guaranteed that the * array will be NULL terminated. */ - assert(info[nr] == NULL); + assert(info[nr - 1] == NULL); out: for (i = 0; i < nr; i++) diff --git a/libuio.h b/libuio.h index 36d7287..cd93875 100644 --- a/libuio.h +++ b/libuio.h @@ -35,6 +35,7 @@ extern "C" { struct uio_info_t; /* base functions */ +void uio_free_info(struct uio_info_t* info); struct uio_info_t **uio_find_devices (); struct uio_info_t *uio_find_by_uio_name (char *uio_name); struct uio_info_t *uio_find_by_uio_num (int num); From b044480583ead681485e4805e3dd64feaabc41ba Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:39:02 +0000 Subject: [PATCH 5/6] Reverted file to previous version --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0c72312..101abd3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Every other copy of the package version number gets its value from here -AC_INIT(libuio, 0.3.0, https://github.com/missinglinkelectronics/libuio/issues) +AC_INIT(libuio, 0.2.8, https://github.com/linutronix/libuio/issues) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) From c36f5d9bacde5079089ae33843a1ef139a8e0025 Mon Sep 17 00:00:00 2001 From: George Castillo <4260836+gmcastil@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:20:18 +0000 Subject: [PATCH 6/6] Removed some comments and an assertion that was unnecessary --- base.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/base.c b/base.c index 00676d6..4cb4a00 100644 --- a/base.c +++ b/base.c @@ -22,7 +22,6 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#include #include #include #include @@ -213,7 +212,6 @@ struct uio_info_t **uio_find_devices () int i, t = 0, nr; snprintf (sysfsname, sizeof (sysfsname), "%s/class/uio", sysfs); - /* This includes the two directories . and .. */ nr = scandir (sysfsname, &namelist, 0, alphasort); if (nr < 0) { @@ -236,12 +234,6 @@ struct uio_info_t **uio_find_devices () info [t++] = create_uio_info (sysfsname, namelist [i]->d_name); } - /* - * Because . and .. should have been in the original result which was - * used to calculate the length to allocate, we are guaranteed that the - * array will be NULL terminated. - */ - assert(info[nr - 1] == NULL); out: for (i = 0; i < nr; i++) @@ -268,29 +260,18 @@ struct uio_info_t *uio_find_by_uio_name (char *uio_name) if (!uio_list) return NULL; - /* - * Iterating over the elements returned from uio_find_devices() assumes - * that either a match is found or the NULL sentinel is reached. - */ for (list = uio_list; *list; list++) { struct uio_info_t *candidate = *list; name = uio_get_name (candidate); - /* - * Free every entry in the result from uio_find_devices() except - * the one that matches - */ if (!strcmp (name, uio_name)) { info = candidate; } else { uio_free_info(candidate); } } - /* If we found a match, all but the matching one should be freed. If no - * match, then the entire result should be freed. In either case, we can - * free the result from uio_find_devices() */ free (uio_list); return info;