libsolv:Handle installed packages in three passes and Fix a couple small static analysis findings for uninitialized structs

Reference:553c69b514
2c4ee52a94
bbd1801748
bbd1801748
Conflict:no
(cherry picked from commit 0c53543aad87e747e574ab1262950baf341a4308)
This commit is contained in:
LuWu 2024-07-16 14:35:31 +08:00 committed by openeuler-sync-bot
parent 8d10f00a2d
commit fedbb6dd93
5 changed files with 362 additions and 1 deletions

View File

@ -0,0 +1,58 @@
From 2c4ee52a948a9ccff2242cd02ac8ce81a0559deb Mon Sep 17 00:00:00 2001
From: David Cantrell <dcantrell@redhat.com>
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++)
{

View File

@ -0,0 +1,72 @@
From bbd1801748e74259f7d8d7d7eee369064961962b Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
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;

View File

@ -0,0 +1,192 @@
From 4c7ce065280f062c52ae19d75344c49e5f562108 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
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 */

View File

@ -0,0 +1,32 @@
From 553c69b514c1ca85a6311373b48c6096886dcff3 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
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)
{

View File

@ -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<hanhuihui5@huawei.com> - 0.7.22-2
- Type:bugfix
- ID:NA