From 08a5ab38c17f7a8218e0d1cc63a607599555d89a Mon Sep 17 00:00:00 2001 From: David Tardon Date: Tue, 21 May 2024 12:33:39 +0200 Subject: [PATCH 1/2] alternatives: ensure the current group is freed ... even if the function fails before the group is fully initialized (and numGroups is incremented). Follow-up-for: 3842524c0000d5f111647fee8d468f32d03c85c5 --- alternatives.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/alternatives.c b/alternatives.c index d15eb2e7..ef98632c 100644 --- a/alternatives.c +++ b/alternatives.c @@ -291,7 +291,7 @@ static int readConfig(struct alternativeSet *set, const char *title, struct { char *facility; char *title; - } *groups = NULL; + } *groups = NULL, newGroup = {}; int numGroups = 0; char linkBuf[PATH_MAX]; int r = 0; @@ -364,8 +364,7 @@ static int readConfig(struct alternativeSet *set, const char *title, goto finish; } - groups = realloc(groups, sizeof(*groups) * (numGroups + 1)); - groups[numGroups].title = strsteal(&line); + newGroup.title = strsteal(&line); nextLine(&buf, &line); if (!line || !*line) { @@ -374,7 +373,11 @@ static int readConfig(struct alternativeSet *set, const char *title, goto finish; } - groups[numGroups++].facility = strsteal(&line); + newGroup.facility = strsteal(&line); + + groups = realloc(groups, sizeof(*groups) * (numGroups + 1)); + groups[numGroups++] = newGroup; + newGroup.title = newGroup.facility = NULL; nextLine(&buf, &line); } @@ -517,6 +520,8 @@ static int readConfig(struct alternativeSet *set, const char *title, free(groups[i].facility); } free(groups); + free(newGroup.title); + free(newGroup.facility); free(line); return r; } From 43342920bc4152613fd602917921ec903656e482 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Tue, 21 May 2024 13:16:39 +0200 Subject: [PATCH 2/2] alternatives: ensure the current alt. is freed if parsing fails --- alternatives.c | 74 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/alternatives.c b/alternatives.c index ef98632c..2ce628a7 100644 --- a/alternatives.c +++ b/alternatives.c @@ -106,6 +106,31 @@ static int usage(int rc) { exit(rc); } +void clearLinkSet(struct linkSet *ls) { + if (!ls) + return; + + free(ls->title); + free(ls->facility); + free(ls->target); +} + +void clearAlternative(struct alternative *alt) { + int i; + + if (!alt) + return; + + clearLinkSet(&alt->leader); + + for (i = 0; i < alt->numFollowers; i++) + clearLinkSet(&alt->followers[i]); + free(alt->followers); + + free(alt->initscript); + free(alt->family); +} + /* * Function to clean path form unnecessary backslashes * It will make from //abcd///efgh/ -> /abcd/efgh/ @@ -294,6 +319,7 @@ static int readConfig(struct alternativeSet *set, const char *title, } *groups = NULL, newGroup = {}; int numGroups = 0; char linkBuf[PATH_MAX]; + struct alternative newAlt = {}; int r = 0; set->alts = NULL; @@ -390,8 +416,6 @@ static int readConfig(struct alternativeSet *set, const char *title, nextLine(&buf, &line); while (line && *line) { - set->alts = realloc(set->alts, (set->numAlts + 1) * sizeof(*set->alts)); - if (*line != '/') { fprintf(stderr, _("path to alternate expected in %s\n"), path); fprintf(stderr, _("unexpected line in %s: %s\n"), path, line); @@ -399,19 +423,18 @@ static int readConfig(struct alternativeSet *set, const char *title, goto finish; } - set->alts[set->numAlts].leader.facility = normalize_path_alloc(groups[0].facility); - set->alts[set->numAlts].leader.title = strdup(groups[0].title); - set->alts[set->numAlts].leader.target = strsteal(&line); - set->alts[set->numAlts].numFollowers = numGroups - 1; + newAlt.leader.facility = normalize_path_alloc(groups[0].facility); + newAlt.leader.title = strdup(groups[0].title); + newAlt.leader.target = strsteal(&line); + newAlt.numFollowers = numGroups - 1; if (numGroups > 1) - set->alts[set->numAlts].followers = malloc( - (numGroups - 1) * sizeof(*set->alts[set->numAlts].followers)); + newAlt.followers = malloc((numGroups - 1) * sizeof(*newAlt.followers)); else - set->alts[set->numAlts].followers = NULL; + newAlt.followers = NULL; - set->alts[set->numAlts].priority = -1; - set->alts[set->numAlts].initscript = NULL; - set->alts[set->numAlts].family = NULL; + newAlt.priority = -1; + newAlt.initscript = NULL; + newAlt.family = NULL; nextLine(&buf, &line); ptr = line; @@ -428,11 +451,11 @@ static int readConfig(struct alternativeSet *set, const char *title, goto finish; } *end = '\0'; - set->alts[set->numAlts].family = strdup(ptr); + newAlt.family = strdup(ptr); ptr = end + 1; } - set->alts[set->numAlts].priority = strtol(ptr, &end, 0); + newAlt.priority = strtol(ptr, &end, 0); if (!end || (end == ptr)) { fprintf(stderr, _("numeric priority expected in %s\n"), path); @@ -444,13 +467,10 @@ static int readConfig(struct alternativeSet *set, const char *title, while (*end && isspace(*end)) end++; if (strlen(end)) { - set->alts[set->numAlts].initscript = strdup(end); + newAlt.initscript = strdup(end); } } - if (set->alts[set->numAlts].priority > set->alts[set->best].priority) - set->best = set->numAlts; - for (i = 1; i < numGroups; i++) { nextLine(&buf, &line); if (line && strlen(line) && *line != '/') { @@ -460,16 +480,21 @@ static int readConfig(struct alternativeSet *set, const char *title, goto finish; } - set->alts[set->numAlts].followers[i - 1].title = - strdup(groups[i].title); - set->alts[set->numAlts].followers[i - 1].facility = - normalize_path_alloc(groups[i].facility); - set->alts[set->numAlts].followers[i - 1].target = - (line && strlen(line)) ? strsteal(&line) : NULL; + newAlt.followers[i - 1].title = strdup(groups[i].title); + newAlt.followers[i - 1].facility = normalize_path_alloc(groups[i].facility); + newAlt.followers[i - 1].target = (line && strlen(line)) ? strsteal(&line) : NULL; } + set->alts = realloc(set->alts, (set->numAlts + 1) * sizeof(*set->alts)); + set->alts[set->numAlts] = newAlt; + + if (newAlt.priority > set->alts[set->best].priority) + set->best = set->numAlts; + set->numAlts++; + memset(&newAlt, 0, sizeof(struct alternative)); + nextLine(&buf, &line); } @@ -523,6 +548,7 @@ static int readConfig(struct alternativeSet *set, const char *title, free(newGroup.title); free(newGroup.facility); free(line); + clearAlternative(&newAlt); return r; }