-
Notifications
You must be signed in to change notification settings - Fork 36
auto-fix bin/sbin duplicates #159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -337,8 +337,84 @@ void nextLine(char **buf, char **line) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *line = parseLine(buf); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int readConfig(struct alternativeSet *set, const char *title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const char *altDir, const char *stateDir, int flags) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* Forward declaration */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int writeStateConf(struct alternativeSet *set, const char *stateDir, int flags); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Detect and remove bin/sbin duplicate alternatives. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Returns the number of duplicates removed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int removeBinSbinDuplicates(struct alternativeSet *set, int flags) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int i, j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int removedCount = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!MERGED_SBIN || set->numAlts < 2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (i = 0; i < set->numAlts; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (j = i + 1; j < set->numAlts; j++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* Check if they differ only in bin/sbin (or are exactly the same) */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (streq_bin(set->alts[i].leader.target, set->alts[j].leader.target)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int k; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* Check if all followers match */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (k = 0; k < set->alts[i].numFollowers; k++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!streq_bin(set->alts[i].followers[k].target, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->alts[j].followers[k].target)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+360
to
+365
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* If any follower didn't match, skip this pair */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (k < set->alts[i].numFollowers) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* Keep i if it is not in /sbin/, otherwise keep j */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (strstr(set->alts[i].leader.target, "/sbin/")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (FL_VERBOSE(flags)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fprintf(stderr, _("removing duplicate alternative: %s (keeping %s)\n"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->alts[i].leader.target, set->alts[j].leader.target); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clearAlternative(&set->alts[i]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->alts[i] = set->alts[j]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (set->best == j) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->best = i; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (set->current == j) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->current = i; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (FL_VERBOSE(flags)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fprintf(stderr, _("removing duplicate alternative: %s (keeping %s)\n"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->alts[j].leader.target, set->alts[i].leader.target); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clearAlternative(&set->alts[j]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* Always remove j (shift everything down) */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (int k = j; k < set->numAlts - 1; k++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set->alts[k] = set->alts[k + 1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+391
to
+392
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (int k = j; k < set->numAlts - 1; k++) { | |
| set->alts[k] = set->alts[k + 1]; | |
| for (int m = j; m < set->numAlts - 1; m++) { | |
| set->alts[m] = set->alts[m + 1]; |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a logic error in this branch. When set->alts[i] is in /sbin/, the code:
- Clears
set->alts[i] - Copies
set->alts[j]toset->alts[i] - Then at line 391-393, shifts all elements from
jdown, overwritingset->alts[j]
This means set->alts[i] now contains a shallow copy of data that was just shifted/moved. Since clearAlternative was already called on the original set->alts[i], and set->alts[j] is being moved (not copied), this creates a double-free risk.
The fix is to NOT shift when keeping j's value in i. The removal should only happen in the else branch. The code should be restructured to:
- Identify which alternative to remove (either i or j)
- Clear that alternative
- If removing i, move j to i's position
- Shift all elements after the removed index down
| } else { | |
| if (FL_VERBOSE(flags)) { | |
| fprintf(stderr, _("removing duplicate alternative: %s (keeping %s)\n"), | |
| set->alts[j].leader.target, set->alts[i].leader.target); | |
| } | |
| clearAlternative(&set->alts[j]); | |
| } | |
| /* Always remove j (shift everything down) */ | |
| for (int k = j; k < set->numAlts - 1; k++) { | |
| set->alts[k] = set->alts[k + 1]; | |
| } | |
| set->numAlts--; | |
| removedCount++; | |
| /* Adjust current and best indices if they're after j */ | |
| if (set->current > j) | |
| set->current--; | |
| if (set->best > j) | |
| set->best--; | |
| /* Adjust j since we removed an element */ | |
| j--; | |
| /* Now remove j (which is now a duplicate of i) */ | |
| for (int k = j; k < set->numAlts - 1; k++) { | |
| set->alts[k] = set->alts[k + 1]; | |
| } | |
| set->numAlts--; | |
| removedCount++; | |
| /* Adjust current and best indices if they're after j */ | |
| if (set->current > j) | |
| set->current--; | |
| if (set->best > j) | |
| set->best--; | |
| /* Adjust j since we removed an element */ | |
| j--; | |
| } else { | |
| if (FL_VERBOSE(flags)) { | |
| fprintf(stderr, _("removing duplicate alternative: %s (keeping %s)\n"), | |
| set->alts[j].leader.target, set->alts[i].leader.target); | |
| } | |
| clearAlternative(&set->alts[j]); | |
| for (int k = j; k < set->numAlts - 1; k++) { | |
| set->alts[k] = set->alts[k + 1]; | |
| } | |
| set->numAlts--; | |
| removedCount++; | |
| /* Adjust current and best indices if they're after j */ | |
| if (set->current > j) | |
| set->current--; | |
| if (set->best > j) | |
| set->best--; | |
| /* Adjust j since we removed an element */ | |
| j--; | |
| } |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After freeing the data structures, the code re-reads the config into the same set structure. However, readConfigInternal initializes set->alts to NULL and set->numAlts to 0 (lines 436-437), but it doesn't reset other fields like set->mode, set->best, and set->current that may have been set during the first read. While readConfigInternal does set these fields (lines 438-440), there's a potential issue if the re-read fails partway through - the set would be in an inconsistent state.
Consider either:
- Memset the entire set structure to 0 before re-reading, or
- Move the initialization of all set fields to the very beginning of readConfigInternal
| /* Zero out the set structure to avoid inconsistent state */ | |
| memset(set, 0, sizeof(*set)); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| [Distribution] | ||
| Distribution=fedora | ||
| Release=41 | ||
| Release=rawhide | ||
|
|
||
| [Build] | ||
| BuildDirectory=build/mkosi.builddir | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function comment states "Returns the number of duplicates removed" but doesn't document important behavior:
bestandcurrentindices/sbin/MERGED_SBINis enabledConsider expanding the documentation: