diff --git a/backport-Fix-a-couple-small-static-analysis-findings-for-uninitialized-structs.patch b/backport-Fix-a-couple-small-static-analysis-findings-for-uninitialized-structs.patch new file mode 100644 index 0000000000000000000000000000000000000000..5629d902daf8db29971875c70491cbdab5319c82 --- /dev/null +++ b/backport-Fix-a-couple-small-static-analysis-findings-for-uninitialized-structs.patch @@ -0,0 +1,58 @@ +From 2c4ee52a948a9ccff2242cd02ac8ce81a0559deb Mon Sep 17 00:00:00 2001 +From: David Cantrell +Date: Tue, 26 Mar 2024 12:13:55 -0400 +Subject: [PATCH] Fix a couple small static analysis findings for uninitialized + structs + +The memset() on the KeyValue is more explicit even though if you trace +the code you will see it fills out the struct. However, it's possible +that not every struct member will be initialized and adding the +memset() makes things more obvious and appeases the static analyzer. + +The queue_init() appeared to just be missing. + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/2c4ee52a948a9ccff2242cd02ac8ce81a0559deb +--- + ext/repo_rpmmd.c | 2 ++ + ext/repo_susetags.c | 1 + + ext/testcase.c | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c +index 1232e4337..5d0f5fe7d 100644 +--- a/ext/repo_rpmmd.c ++++ b/ext/repo_rpmmd.c +@@ -609,6 +609,8 @@ fill_cshash_from_new_solvables(struct parsedata *pd) + KeyValue kv; + Repokey *key; + ++ memset(&kv, 0, sizeof(kv)); ++ + for (i = pd->first; i < pool->nsolvables; i++) + { + if (pool->solvables[i].repo != pd->repo) +diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c +index dc60aa49c..544974be5 100644 +--- a/ext/repo_susetags.c ++++ b/ext/repo_susetags.c +@@ -339,6 +339,7 @@ lookup_shared_id(Repodata *data, Id p, Id keyname, Id voidid, int uninternalized + if (uninternalized) + { + KeyValue kv; ++ memset(&kv, 0, sizeof(kv)); + Repokey *key = repodata_lookup_kv_uninternalized(data, p, keyname, &kv); + if (!key) + return 0; +diff --git a/ext/testcase.c b/ext/testcase.c +index f46f738d3..7b6179b5d 100644 +--- a/ext/testcase.c ++++ b/ext/testcase.c +@@ -1497,6 +1497,7 @@ testcase_solverresult(Solver *solv, int resultflags) + if ((resultflags & TESTCASE_RESULT_USERINSTALLED) != 0) + { + Queue q; ++ queue_init(&q); + solver_get_userinstalled(solv, &q, 0); + for (i = 0; i < q.count; i++) + { diff --git a/backport-Handle-installed-packages-in-three-passes.patch b/backport-Handle-installed-packages-in-three-passes.patch new file mode 100644 index 0000000000000000000000000000000000000000..4bdfbe21d5895551a646baf422cc3b5bd3f9292a --- /dev/null +++ b/backport-Handle-installed-packages-in-three-passes.patch @@ -0,0 +1,72 @@ +From bbd1801748e74259f7d8d7d7eee369064961962b Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 15:25:47 +0100 +Subject: [PATCH] Handle installed packages in three passes + +Fixes issue #550 + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/bbd1801748e74259f7d8d7d7eee369064961962b +--- + src/solver.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 741aa1b2f..a1a41f677 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1836,7 +1836,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + { + Pool *pool = solv->pool; + Repo *installed = solv->installed; +- int i, n, pass; ++ int i, n, pass, startpass; + int installedpos = solv->installedpos; + Solvable *s; + Id p, pp; +@@ -1845,10 +1845,14 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving installed packages\n"); + if (!installedpos) + installedpos = installed->start; +- /* we use two passes if we need to update packages +- * to create a better user experience */ +- for (pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; pass < 2; ) ++ /* we use passes if we need to update packages to create a better user experience: ++ * pass 0: update the packages requested by the user ++ * pass 1: keep the installed packages if we can ++ * pass 2: update the packages that could not be kept */ ++ startpass = solv->updatemap_all ? 2 : solv->updatemap.size ? 0 : 1; ++ for (pass = startpass; pass < 3; ) + { ++ int needpass2 = 0; + int passlevel = level; + Id *specialupdaters = solv->specialupdaters; + /* start with installedpos, the position that gave us problems the last time */ +@@ -1880,6 +1884,11 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + * the installed package and not replace it with a newer version */ + if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { ++ if (pass == 1) ++ { ++ needpass2 = 1; /* first do the packages we do not want/need to update */ ++ continue; ++ } + if (dq->count) + queue_empty(dq); + /* find update candidates */ +@@ -1964,12 +1973,14 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + if (level < origlevel) + break; /* ran into trouble */ + /* re-run all passes */ +- pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; ++ pass = startpass; + continue; + } + /* reset installedpos, advance to next pass */ + installedpos = installed->start; + pass++; ++ if (pass == 2 && !needpass2) ++ break; + } + solv->installedpos = installedpos; + return level; diff --git a/backport-Move-special-updaters-handling-into-its-own-function.patch b/backport-Move-special-updaters-handling-into-its-own-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..89c9726c8b768c7e0c21efcab6e2e08db0fe1ff1 --- /dev/null +++ b/backport-Move-special-updaters-handling-into-its-own-function.patch @@ -0,0 +1,192 @@ +From 4c7ce065280f062c52ae19d75344c49e5f562108 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 14:42:25 +0100 +Subject: [PATCH] Move special updaters handling into its own function + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/4c7ce065280f062c52ae19d75344c49e5f562108 +--- + src/solver.c | 127 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 71 insertions(+), 56 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 0c3333d87..741aa1b2f 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1788,6 +1788,49 @@ prune_to_update_targets(Solver *solv, Id *cp, Queue *q) + queue_truncate(q, j); + } + ++static void ++get_special_updaters(Solver *solv, int i, Rule *rr, Queue *dq) ++{ ++ Pool *pool = solv->pool; ++ Repo *installed = solv->installed; ++ int specoff = solv->specialupdaters[i - installed->start]; ++ int j, d; ++ Id p; ++ ++ /* special multiversion handling, make sure best version is chosen */ ++ if (rr->p == i && solv->decisionmap[i] >= 0) ++ queue_push(dq, i); ++ for (d = specoff; (p = pool->whatprovidesdata[d]) != 0; d++) ++ if (solv->decisionmap[p] >= 0) ++ queue_push(dq, p); ++ /* if we have installed packages try to find identical ones to get ++ * repo priorities. see issue #343 */ ++ for (j = 0; j < dq->count; j++) ++ { ++ Id p2 = dq->elements[j]; ++ if (pool->solvables[p2].repo != installed) ++ continue; ++ for (d = specoff; (p = pool->whatprovidesdata[d]) != 0; d++) ++ { ++ if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed) ++ continue; ++ if (solvable_identical(pool->solvables + p, pool->solvables + p2)) ++ queue_push(dq, p); /* identical to installed, put it on the list so we have a repo prio */ ++ } ++ } ++ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) ++ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ if (dq->count) ++ { ++ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE); ++ p = dq->elements[0]; ++ if (p != i && solv->decisionmap[p] == 0) ++ dq->count = 1; ++ else ++ dq->count = 0; ++ } ++} ++ + static int + resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + { +@@ -1804,7 +1847,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + installedpos = installed->start; + /* we use two passes if we need to update packages + * to create a better user experience */ +- for (pass = solv->updatemap.size ? 0 : 1; pass < 2; ) ++ for (pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; pass < 2; ) + { + int passlevel = level; + Id *specialupdaters = solv->specialupdaters; +@@ -1812,7 +1855,6 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + for (i = installedpos, n = installed->start; n < installed->end; i++, n++) + { + Rule *r, *rr; +- Id d; + + if (i == installed->end) + i = installed->start; +@@ -1836,48 +1878,20 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + /* check if we should update this package to the latest version + * noupdate is set for erase jobs, in that case we want to deinstall + * the installed package and not replace it with a newer version */ +- if (dq->count) +- queue_empty(dq); + if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { +- if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) ++ if (dq->count) ++ queue_empty(dq); ++ /* find update candidates */ ++ if (specialupdaters && specialupdaters[i - installed->start] != 0) + { +- int j; +- /* special multiversion handling, make sure best version is chosen */ +- if (rr->p == i && solv->decisionmap[i] >= 0) +- queue_push(dq, i); +- while ((p = pool->whatprovidesdata[d++]) != 0) +- if (solv->decisionmap[p] >= 0) +- queue_push(dq, p); +- for (j = 0; j < dq->count; j++) +- { +- Id p2 = dq->elements[j]; +- if (pool->solvables[p2].repo != installed) +- continue; +- d = specialupdaters[i - installed->start]; +- while ((p = pool->whatprovidesdata[d++]) != 0) +- { +- if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed) +- continue; +- if (solvable_identical(pool->solvables + p, pool->solvables + p2)) +- queue_push(dq, p); /* identical to installed, put it on the list so we have a repo prio */ +- } +- } +- if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) +- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ get_special_updaters(solv, i, rr, dq); ++ /* if we have an update set rr to the feature rule */ + if (dq->count) + { +- policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE); +- p = dq->elements[0]; +- if (p != i && solv->decisionmap[p] == 0) +- { +- rr = solv->rules + solv->featurerules + (i - solv->installed->start); +- if (!rr->p) /* update rule == feature rule? */ +- rr = rr - solv->featurerules + solv->updaterules; +- dq->count = 1; +- } +- else +- dq->count = 0; ++ rr = solv->rules + solv->featurerules + (i - solv->installed->start); ++ if (!rr->p) /* update rule == feature rule? */ ++ rr = rr - solv->featurerules + solv->updaterules; + } + } + else +@@ -1894,24 +1908,25 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + queue_push(dq, p); + } + } +- } +- if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) +- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); +- /* install best version */ +- if (dq->count) +- { +- olevel = level; +- level = selectandinstall(solv, level, dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED); +- if (level <= olevel) ++ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) ++ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ /* install best version */ ++ if (dq->count) + { +- if (level < passlevel) +- break; /* trouble */ +- if (level < olevel) +- n = installed->start; /* redo all */ +- i--; +- n--; +- continue; ++ olevel = level; ++ level = selectandinstall(solv, level, dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED); ++ if (level <= olevel) ++ { ++ if (level < passlevel) ++ break; /* trouble */ ++ if (level < olevel) ++ n = installed->start; /* redo all */ ++ i--; ++ n--; ++ continue; ++ } + } ++ /* check original package even if we installed an update */ + } + /* if still undecided keep package */ + if (solv->decisionmap[i] == 0) +@@ -1949,7 +1964,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + if (level < origlevel) + break; /* ran into trouble */ + /* re-run all passes */ +- pass = solv->updatemap.size ? 0 : 1; ++ pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; + continue; + } + /* reset installedpos, advance to next pass */ + diff --git a/backport-resolve_installed-remove-dead-code.patch b/backport-resolve_installed-remove-dead-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..199c93458f8dc32e76270f9bc7f2e3ac5f006cc8 --- /dev/null +++ b/backport-resolve_installed-remove-dead-code.patch @@ -0,0 +1,32 @@ +From 553c69b514c1ca85a6311373b48c6096886dcff3 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 12:43:50 +0100 +Subject: [PATCH] resolve_installed: remove dead code + +Since we simplified our dup handling the update rules always +start with the installed package. + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/553c69b514c1ca85a6311373b48c6096886dcff3 +--- + src/solver.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 363d88734..0c3333d87 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1835,11 +1835,10 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + + /* check if we should update this package to the latest version + * noupdate is set for erase jobs, in that case we want to deinstall +- * the installed package and not replace it with a newer version +- * rr->p != i is for dup jobs where the installed package cannot be kept */ ++ * the installed package and not replace it with a newer version */ + if (dq->count) + queue_empty(dq); +- if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i))) ++ if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { + if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) + { diff --git a/libsolv.spec b/libsolv.spec index f37e17221ac363110c95f58d734ec18cbde6c765..e92d17aa04149a03b74bd6440af3bc9464156ad6 100644 --- a/libsolv.spec +++ b/libsolv.spec @@ -15,7 +15,7 @@ Name: libsolv Version: 0.7.22 -Release: 2 +Release: 3 Summary: Package dependency solver License: BSD URL: https://github.com/openSUSE/libsolv @@ -25,6 +25,10 @@ Patch0: Fix-memory-leak-when-using-testsolv-to-execute-cases.patch Patch6001: backport-Treat-condition-both-as-positive-and-negative-literal-in-pool_add_pos_literals_complex_dep.patch Patch6002: backport-Add-testcase-for-last-commit.patch Patch6003: backport-choice-rules-also-do-solver_choicerulecheck-for-package-downgrades.patch +Patch6004: backport-resolve_installed-remove-dead-code.patch +Patch6005: backport-Move-special-updaters-handling-into-its-own-function.patch +Patch6006: backport-Handle-installed-packages-in-three-passes.patch +Patch6007: backport-Fix-a-couple-small-static-analysis-findings-for-uninitialized-structs.patch BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel BuildRequires: libxml2-devel xz-devel bzip2-devel @@ -218,6 +222,9 @@ Python 3 version. %{_mandir}/man3/%{name}*.3* %changelog +* Tue Jul 16 2024 LuWu<2398491106@qq.com> - 0.7.22-3 +- Handle installed packages in three passes + * Sat Aug 19 2023 hanhuihui - 0.7.22-2 - Type:bugfix - ID:NA