michal-grzedzicki / rpms / rpm

Forked from rpms/rpm 5 months ago
Clone
Blob Blame History Raw
From 050b392f8c11d111379e0d2bac52762beb97b3ae Mon Sep 17 00:00:00 2001
Message-Id: <050b392f8c11d111379e0d2bac52762beb97b3ae.1559645935.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 2 Apr 2019 12:57:11 +0300
Subject: [PATCH] Fix segfault on fingerprinting symlink round (RhBug:1660232)

Both yum and dnf perform a test-transaction before the real thing,
and both neglet to check for an error code from the test-transaction
when there are no problem objects to return. Which can happen in
some special cases, such a using different vsflags between initial
package read and transaction (which is what both yum and dnf do),
which can cause the in-transaction package open fail on corrupt packages.
And when this failed transaction is fed back to rpmtsRun(), it
segfaults in fingerprinting as the second loop of symlink checking
doesn't check for NULL's element files like the first loop does.

Add the missing NULL check and remove bogus "can't happen" comment to fix.

FWIW, the scenario with different vsflags and corrupted packages doesn't
happen by default in rpm >= 4.14.2, the corrupt package gets caught
in the verify stage which does create problem objects and thus both
yum and dnf abort as they should.
---
 lib/fprint.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/fprint.c b/lib/fprint.c
index b810e4d2b..ab1891961 100644
--- a/lib/fprint.c
+++ b/lib/fprint.c
@@ -488,7 +488,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
 	(void) rpmsqPoll();
 
 	if ((fi = rpmteFiles(p)) == NULL)
-	    continue;	/* XXX can't happen */
+	    continue;
 
 	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
 	rpmfilesFpLookup(fi, fpc);
@@ -522,6 +522,9 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
     while ((p = rpmtsiNext(pi, 0)) != NULL) {
 	(void) rpmsqPoll();
 
+	if ((fi = rpmteFiles(p)) == NULL)
+	    continue;
+
 	fs = rpmteGetFileStates(p);
 	fc = rpmfsFC(fs);
 	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
@@ -531,6 +534,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
 	    fpLookupSubdir(symlinks, fpc, p, i);
 	}
 	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+	rpmfilesFree(fi);
     }
     rpmtsiFree(pi);
 
-- 
2.21.0