diff --git a/backport-Fix-rpmds-segfault-s-memleaks-on-incomplete-header-d.patch b/backport-Fix-rpmds-segfault-s-memleaks-on-incomplete-header-d.patch new file mode 100644 index 0000000000000000000000000000000000000000..e42b6667871529a293ec3d66b8a08da29111c7f1 --- /dev/null +++ b/backport-Fix-rpmds-segfault-s-memleaks-on-incomplete-header-d.patch @@ -0,0 +1,126 @@ +From b3b87f803ccb095b68ac660df9df43dcf0290b4e Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 16 Sep 2025 12:44:10 +0300 +Subject: [PATCH] Fix rpmds segfault(s) + memleaks on incomplete header data + +The rpmds code tries to handle missing flags and evr from ancient rpm +versions (prior to 3.0.2) but even if it once did, it no longer does and +nobody has noticed. We don't even support installing v3 packages anymore +so lets just drop the pretense and require the arrays to be present. + +There are also memory leaks on the error paths, fix those while at it. + +Add a few test-cases to exercise it too. + +Conflict:Rename rpmds.cc to rpmds.c . Include stdbool and context adaptation. +Reference:https://github.com/rpm-software-management/rpm/commit/b3b87f803ccb095b68ac660df9df43dcf0290b4e + +--- + lib/rpmds.c | 24 +++++++++++++----------- + tests/rpmpython.at | 38 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 11 deletions(-) + +diff --git a/lib/rpmds.c b/lib/rpmds.c +index 3ece7d4b3..4129c9f52 100644 +--- a/lib/rpmds.c ++++ b/lib/rpmds.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + #include "lib/rpmds_internal.h" + +@@ -264,27 +264,28 @@ rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags) + if (headerGet(h, tagN, &names, HEADERGET_MINMEM)) { + struct rpmtd_s evr, dflags, tindices; + rpm_count_t count = rpmtdCount(&names); ++ bool err = false; + + headerGet(h, tagEVR, &evr, HEADERGET_MINMEM); +- if (evr.count && evr.count != count) { +- rpmtdFreeData(&evr); +- return NULL; +- } +- + headerGet(h, tagF, &dflags, HEADERGET_ALLOC); +- if (dflags.count && dflags.count != count) { +- rpmtdFreeData(&dflags); +- return NULL; +- } ++ if (evr.count != count || dflags.count != count) ++ err = true; + + if (tagTi) { + headerGet(h, tagTi, &tindices, HEADERGET_ALLOC); +- if (tindices.count && tindices.count != count) { ++ if (tindices.count != count) { + rpmtdFreeData(&tindices); +- return NULL; ++ err = true; + } + } + ++ if (err) { ++ rpmtdFreeData(&names); ++ rpmtdFreeData(&evr); ++ rpmtdFreeData(&dflags); ++ goto exit; ++ } ++ + ds = rpmdsCreate(pool, tagN, Type, count, headerGetInstance(h)); + + ds->N = names.count ? rpmtdToPool(&names, ds->pool) : NULL; +diff --git a/tests/rpmpython.at b/tests/rpmpython.at +index d112b32ca..2b28d47b7 100644 +--- a/tests/rpmpython.at ++++ b/tests/rpmpython.at +@@ -704,6 +704,44 @@ aabb 0x40000 3 + ], + []) + ++RPMPY_TEST([dependency sets 6.1],[ ++h = rpm.hdr() ++h['requirename'] = ['aa', 'bb', 'cc'] ++h['requireversion'] = ['1', '2', '3'] ++h['requireflags'] = [0, 1, 2] ++for d in rpm.ds(h, rpm.RPMTAG_REQUIRENAME): ++ print(d.N(), d.EVR(), d.Flags()) ++], ++[aa 1 0 ++bb 2 1 ++cc 3 2 ++]) ++ ++# insufficient/malformed header data, must not print anything ++RPMPY_TEST([dependency sets 6.2],[ ++h = rpm.hdr() ++h['requirename'] = ['aa', 'bb', 'cc'] ++for d in rpm.ds(h, rpm.RPMTAG_REQUIRENAME): ++ print(d.N(), d.EVR(), d.Flags()) ++h = rpm.hdr() ++h['requirename'] = ['aa', 'bb', 'cc'] ++h['requireflags'] = [0, 1, 2] ++for d in rpm.ds(h, rpm.RPMTAG_REQUIRENAME): ++ print(d.N(), d.EVR(), d.Flags()) ++h = rpm.hdr() ++h['requirename'] = ['aa', 'bb', 'cc'] ++h['requireversion'] = ['1', '2', '3'] ++for d in rpm.ds(h, rpm.RPMTAG_REQUIRENAME): ++ print(d.N(), d.EVR(), d.Flags()) ++h = rpm.hdr() ++h['requirename'] = ['aa', 'bb', 'cc'] ++h['requireversion'] = ['1', '2'] ++h['requireflags'] = [0, 1, 2, 4] ++for d in rpm.ds(h, rpm.RPMTAG_REQUIRENAME): ++ print(d.N(), d.EVR(), d.Flags()) ++], ++[]) ++ + RPMPY_TEST([file info sets 1],[ + ts = rpm.ts() + h = ts.hdrFromFdno('${RPMDATA}/RPMS/hello-2.0-1.i686.rpm') +-- +2.43.0 + diff --git a/backport-Fix-rpmds-trigger-index-to-be-optional-as-originally.patch b/backport-Fix-rpmds-trigger-index-to-be-optional-as-originally.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1cc012fa7f171f47e85f74308cc566f9a773d1c --- /dev/null +++ b/backport-Fix-rpmds-trigger-index-to-be-optional-as-originally.patch @@ -0,0 +1,63 @@ +From 62be8046e6d6d8f4d99b259963efd749f1de3f33 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 15 Sep 2025 14:07:06 +0300 +Subject: [PATCH] Fix rpmds trigger index to be optional as originally intended + +Commit e66bf7425b450c9baf52c280fb892031b38b15df the tag value for +non-existent from RPMTAG_NOT_FOUND to 0 but missed a whole bunch of +cases actually relying on that explicit value for initializing the +array. Also, in the case of a single item ds, only initialize the array if +there is an index. + +Shouldn't affect actual behavior. + +Conflict:Context adaptation. +Reference:https://github.com/rpm-software-management/rpm/commit/62be8046e6d6d8f4d99b259963efd749f1de3f33 + +--- + lib/rpmds.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/lib/rpmds.c b/lib/rpmds.c +index 518231174..f44174f45 100644 +--- a/lib/rpmds.c ++++ b/lib/rpmds.c +@@ -277,7 +277,7 @@ rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags) + return NULL; + } + +- if (tagTi != RPMTAG_NOT_FOUND) { ++ if (tagTi) { + headerGet(h, tagTi, &tindices, HEADERGET_ALLOC); + if (tindices.count && tindices.count != count) { + rpmtdFreeData(&tindices); +@@ -290,7 +290,7 @@ rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags) + ds->N = names.count ? rpmtdToPool(&names, ds->pool) : NULL; + ds->EVR = evr.count ? rpmtdToPool(&evr, ds->pool): NULL; + ds->Flags = dflags.data; +- if (tagTi != RPMTAG_NOT_FOUND) { ++ if (tagTi) { + ds->ti = tindices.data; + } + +@@ -388,7 +388,7 @@ static rpmds singleDSPool(rpmstrPool pool, rpmTagVal tagN, + ds->EVR[0] = EVR; + ds->Flags = xmalloc(sizeof(*ds->Flags)); + ds->Flags[0] = Flags; +- if (tagTi != RPMTAG_NOT_FOUND) { ++ if (tagTi && triggerIndex != -1) { + ds->ti = xmalloc(sizeof(*ds->ti)); + ds->ti[0] = triggerIndex; + } +@@ -519,7 +519,7 @@ int rpmdsPutToHeader(rpmds ds, Header h) + headerPutString(h, tagN, rpmdsN(pi)); + headerPutString(h, tagEVR, rpmdsEVR(pi)); + headerPutUint32(h, tagF, &flags, 1); +- if (tagTi != RPMTAG_NOT_FOUND) { ++ if (tagTi) { + headerPutUint32(h, tagTi, &index, 1); + } + } +-- +2.43.0 + diff --git a/backport-Fix-segfault-in-rpmgraph.patch b/backport-Fix-segfault-in-rpmgraph.patch new file mode 100644 index 0000000000000000000000000000000000000000..1d42c44a6e3a27d70005018f461fff3165bc20c3 --- /dev/null +++ b/backport-Fix-segfault-in-rpmgraph.patch @@ -0,0 +1,32 @@ +From be3f8d180c8248ce87fc96f1d99cbe637c1fe1c0 Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Tue, 9 Sep 2025 12:39:20 +0200 +Subject: [PATCH] Fix segfault in rpmgraph + +The rootDir needs to be set explicitly nowadays, even if passing just +NULL. + +Resolves: #3925 + +Conflict:Rename rpmgraph.cc to rpmgraph.c +Reference:https://github.com/rpm-software-management/rpm/commit/be3f8d180c8248ce87fc96f1d99cbe637c1fe1c0 + +--- + tools/rpmgraph.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/rpmgraph.c b/tools/rpmgraph.c +index 9edf3968b..33fe8da2c 100644 +--- a/tools/rpmgraph.c ++++ b/tools/rpmgraph.c +@@ -241,6 +241,7 @@ main(int argc, char *argv[]) + exit(EXIT_FAILURE); + + ts = rpmtsCreate(); ++ (void) rpmtsSetRootDir(ts, NULL); + vsflags |= rpmcliVSFlags; + (void) rpmtsSetVSFlags(ts, vsflags); + +-- +2.43.0 + diff --git a/backport-rpmgraph-Prevent-memory-leaks-in-error-handling.patch b/backport-rpmgraph-Prevent-memory-leaks-in-error-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..260549f5075b488770542e3348a2ff6a53be4fc0 --- /dev/null +++ b/backport-rpmgraph-Prevent-memory-leaks-in-error-handling.patch @@ -0,0 +1,62 @@ +From 4db8dd3864ba403f8bb9c309b461a05820375d16 Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Wed, 10 Sep 2025 11:41:22 +0200 +Subject: [PATCH] rpmgraph: Prevent memory leaks in error handling + +Just setting a pointer to NULL does not free the memory. Call free on +the input paths we are ignoring. + +Conflict:Rename rpmgraph.cc to rpmgraph.c +Reference:https://github.com/rpm-software-management/rpm/commit/4db8dd3864ba403f8bb9c309b461a05820375d16 + +--- + tools/rpmgraph.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/rpmgraph.c b/tools/rpmgraph.c +index 33fe8da2c..0a6b9a8ed 100644 +--- a/tools/rpmgraph.c ++++ b/tools/rpmgraph.c +@@ -96,7 +96,8 @@ restart: + Fclose(fd); + fd = NULL; + } +- numFailed++; *fnp = NULL; ++ numFailed++; ++ *fnp = _free(*fnp); + continue; + } + +@@ -111,7 +112,8 @@ restart: + case RPMRC_FAIL: + default: + rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), *fnp); +- numFailed++; *fnp = NULL; ++ numFailed++; ++ *fnp = _free(*fnp); + break; + case RPMRC_OK: + rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName, 0, NULL); +@@ -133,7 +135,8 @@ maybe_manifest: + Fclose(fd); + fd = NULL; + } +- numFailed++; *fnp = NULL; ++ numFailed++; ++ *fnp = _free(*fnp); + break; + } + +@@ -151,7 +154,8 @@ maybe_manifest: + goto restart; + } + +- numFailed++; *fnp = NULL; ++ numFailed++; ++ *fnp = _free(*fnp); + break; + } + +-- +2.43.0 + diff --git a/backport-rpmrc-Drop-left-over-free.patch b/backport-rpmrc-Drop-left-over-free.patch new file mode 100644 index 0000000000000000000000000000000000000000..69f6f79dc4014321d40f77a701628541ec2d9e7b --- /dev/null +++ b/backport-rpmrc-Drop-left-over-free.patch @@ -0,0 +1,30 @@ +From aeb410f0a9bf98ccde67ed5898475e137c628ab3 Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Fri, 29 Aug 2025 16:08:23 +0200 +Subject: [PATCH] rpmrc: Drop left over free() + +This line should have been removed in 2c12725620193da7078693cb893c3dab152a0dfa +to keep the name of the current rpmrc file around for error messages. + +Conflict:Rename rpmrc.cc to rpmrc.c +Reference:https://github.com/rpm-software-management/rpm/commit/aeb410f0a9bf98ccde67ed5898475e137c628ab3 + +--- + lib/rpmrc.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/lib/rpmrc.c b/lib/rpmrc.c +index 7569bb705..2b3baeddc 100644 +--- a/lib/rpmrc.c ++++ b/lib/rpmrc.c +@@ -527,7 +527,6 @@ static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn) + free(name); + } + rpmSetVarArch(ctx, option->var, val, arch); +- fn = _free(fn); + + } else { /* For arch/os compatibility tables ... */ + int gotit; +-- +2.43.0 + diff --git a/rpm.spec b/rpm.spec index 412566902922950b6bd4546b2820b8e94fe19f39..f09a1ba0bc4f8f77e8719357e0b7dbb3d1dfedd2 100644 --- a/rpm.spec +++ b/rpm.spec @@ -1,6 +1,6 @@ Name: rpm Version: 4.17.0 -Release: 48 +Release: 49 Summary: RPM Package Manager License: GPLv2+ URL: http://www.rpm.org/ @@ -135,6 +135,11 @@ Patch6103: backport-Return-1-from-fdSize-for-non-regular-files.patch Patch6104: backport-Check-RPATH-and-RUNPATH-separately-in-check-rpaths.patch Patch6105: backport-Avoid-Python-reference-leaks.patch Patch6106: backport-Ensure-header-object-is-cleaned-even-in-case-of-an-e.patch +Patch6107: backport-rpmrc-Drop-left-over-free.patch +Patch6108: backport-Fix-segfault-in-rpmgraph.patch +Patch6109: backport-rpmgraph-Prevent-memory-leaks-in-error-handling.patch +Patch6110: backport-Fix-rpmds-trigger-index-to-be-optional-as-originally.patch +Patch6111: backport-Fix-rpmds-segfault-s-memleaks-on-incomplete-header-d.patch BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel BuildRequires: zlib-devel zstd-devel >= 1.3.8 xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel @@ -425,6 +430,9 @@ make check || (cat tests/rpmtests.log; exit 0) %{_mandir}/man1/gendiff.1* %changelog +* Wed Dec 17 2025 hugel - 4.17.0-49 +- backport community patches + * Thu Aug 14 2025 fuanan - 4.17.0-48 - sync patches from upstream