From 6b9eddae49a25c091728e52849b00812f9cedd94 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 1 Mar 2020 13:15:36 +0000 Subject: [PATCH] config_libconfig: fix xdgConfigDirectories Fixed 2 problems: 1. Made sure the returned list is NULL terminated. 2. Allocate the duplicated string and the return list together, so the duplicated string will be freed as we free the list. Fixed a memory leak. Fixes #324 Signed-off-by: Yuxuan Shui --- src/config_libconfig.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/config_libconfig.c b/src/config_libconfig.c index 6b0316ac..6326583d 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -53,26 +53,34 @@ const char *xdgConfigHome(void) { } const char * const * xdgConfigDirectories(void) { - char *dirs, *path, *xdgd = getenv("XDG_CONFIG_DIRS"); - char **dir_list = {0}; - unsigned int sep = 0; + char *xdgd = getenv("XDG_CONFIG_DIRS"); + size_t count = 0; - if (!xdgd) xdgd = ":/etc/xdg:"; - - dirs = strdup(xdgd); - CHECK(dirs != NULL); - path = strtok(dirs, ":"); - - while (path) { - dir_list = realloc(dir_list, sizeof(char*) * ++sep); - - CHECK(dir_list); - - dir_list[sep-1] = path; - - path = strtok(NULL, ":"); + if (!xdgd) { + xdgd = "/etc/xdg"; } + for (int i = 0; xdgd[i]; i++) { + if (xdgd[i] == ':') { + count++; + } + } + + // Store the string and the result pointers together so it can be + // freed together + char **dir_list = cvalloc(sizeof(char *) * (count + 2) + strlen(xdgd) + 1); + auto dirs = strcpy((char *)dir_list + sizeof(char *) * (count + 2), xdgd); + auto path = dirs; + + for (size_t i = 0; i < count; i++) { + dir_list[i] = path; + path = strchr(path, ':'); + *path = '\0'; + path++; + } + dir_list[count] = path; + dir_list[count + 1] = NULL; + return (const char * const *)dir_list; }