[Rpm-maint] rpm4.14 makes perl-RPM4 testsuite to segfault (was: Re: [Rpm-announce] RPM 4.14.0 release candidate 2 is out)

Thierry Vignaud thierry.vignaud at gmail.com
Wed Oct 4 10:25:59 UTC 2017


On 3 October 2017 at 09:12, Panu Matilainen <pmatilai at redhat.com> wrote:
>>>>>> Also this new rpm introduced segfault regressions in both RPM4 & urpmi
>>>>>> testsuites
>>>>>> See attached gdb traces in BUG*.txt
>>>>>> valgrind seems to hint about invalid writes/reads
>>>>>> See you
>>>>>
>>>>>
>>>>>
>>>>> The urpmi issue is when checking bogus pkgs.
>>>>> The RPM4 issue is when traversing the transaction (not the rpmdb)
>>>>> Attached are the valgrind outputs
>>>>>
>>>>
>>>> So we have stuff like
>>>>
>>>> ==14087== Invalid write of size 4
>>>> ==14087==    at 0x103AA6DD: headerUnlink (header.c:188)
>>>> ==14087==    by 0x103AA6DD: headerFree (header.c:194)
>>>> ==14087==    by 0xFF69314: XS_RPM4__Header_DESTROY (RPM4.xs:890)
>>>> ==14087==    by 0x3F512E2C40: Perl_pp_entersub (pp_hot.c:4231)
>>>> ==14087==    by 0x3F5125551E: Perl_call_sv (perl.c:2848)
>>>> ==14087==    by 0x3F512E7C09: S_curse (sv.c:6987)
>>>> ==14087==    by 0x3F512E84F7: Perl_sv_clear (sv.c:6591)
>>>> ==14087==    by 0x3F512E898D: Perl_sv_free2 (sv.c:7088)
>>>> ==14087==    by 0x3F513182E6: UnknownInlinedFun (inline.h:200)
>>>> ==14087==    by 0x3F513182E6: Perl_free_tmps (scope.c:212)
>>>> ==14087==    by 0x3F512DAD74: Perl_pp_nextstate (pp_hot.c:52)
>>>> ==14087==    by 0x3F512DAA55: Perl_runops_standard (run.c:41)
>>>> ==14087==    by 0x3F5125D236: S_run_body (perl.c:2524)
>>>> ==14087==    by 0x3F5125D236: perl_run (perl.c:2447)
>>>> ==14087==    by 0x400C79: main (perlmain.c:123)
>>>> ==14087==  Address 0xffeffef8c is on thread 1's stack
>>>> ==14087==  396 bytes below stack pointer
>>>>
>>>> ...and all the failures are around headerFree(), but none of the traces
>>>> go
>>>> into rpm itself, so I dont really know what does "traversing the
>>>> transaction" actually mean.
>>>
>>>
>>> in both URPM & RPM4 bindings, there's a family of traverse functions
>>> that enable to execute a callback on each package of either:
>>> - rpmdb
>>> - the current transaction,
>>> - pkgs header from an hdlist file
>>> - synthetic metadata from a synthesis file
>>> calling the callback on the currrent header
>>>
>>> See:
>>> - Db_traverse*() & Trans_traverse() in perl-URPM/URPM.xs
>>> - Ts_traverse() in RPM4-0.36/src/RPM4.xs
>>>
>>> It's loosely documented at
>>> http://search.cpan.org/~tvignaud/URPM-5.12/URPM.pm or
>>>
>>> http://search.cpan.org/~tvignaud/RPM4-0.36/lib/RPM4/Transaction.pm#Hdlist::Db-%3Etraverse_headers(sub)
>>> (RPM4's doc is very incomplete -- I'm only maintaining this b/c other
>>> tools depend on that and I cannot break them when upgrading rpm)
>>>
>>>> But the problem is simply with perl-RPM4 and
>>>> urpmi passing uninitialized variables to headerFree().
>>>>
>>>> What changed in rpm is that rpmReadPackageFile() no longer does this as
>>>> the
>>>> first thing:
>>>>
>>>>      if (hdrp)
>>>>          *hdrp = NULL;
>>>>
>>>> Ie if you pass an uninitialized pointer as hdrp, it remains
>>>> uninitialized
>>>> unless rpmReadPackageFile() returns with a success code.
>>>> Which is how I think it should be, but it does deserve a release note on
>>>> the
>>>> changed API.
>>>>
>>>> So the moral of the story is basically: if you depend on your variables
>>>> being initialized, initialize them by yourself. It's a good practise
>>>> anyway.
>>>
>>>
>>> I'll check for uninitialized variables later today
>>
>>
>> Actually the bug happen when running the transaction
>>
>
> Right, that makes sense, there's a second rpmReadPackageFile() inside
> transaction run.

Intestingly, perl-RPM4 no more segfaults (there still faillures
though) if I alter the transrun() method (which calls rpmtsRun in
rpmlib) 's perl callback to *not* call std rpmShowProgress())
See attached patch

Aka previously it runs both the passed perl callback + rpmlib default
callback which worked smoothly.
But since rpm-4.14, calling std rpm callback results a segfault...
I'm happy to not call that and I don't think we have any tool actually
running transactions^W installing packages through RPM4 right now but
still that's a regression in rpm...
Maybe some new unlink call or sg like that
-------------- next part --------------
diff -up ./src/RPM4.xs.tv ./src/RPM4.xs
--- ./src/RPM4.xs.tv	2017-10-03 20:26:06.787713414 +0200
+++ ./src/RPM4.xs	2017-10-03 20:23:09.328596076 +0200
@@ -292,6 +292,7 @@ static void *
     SPAGAIN;
   
     /* Running rpmlib callback, returning its value */
+    return NULL;
     return rpmShowProgress(h,
             what, 
             amount, 
diff -up ./t/05transaction.t.tv ./t/05transaction.t
--- ./t/05transaction.t.tv	2017-10-03 19:56:01.565902942 +0200
+++ ./t/05transaction.t	2017-10-03 19:59:33.485538487 +0200
@@ -71,7 +71,11 @@ ok($ts->transcheck == 0, "Checking trans
 ok($ts->transorder == 0, "Run transaction order");
 
 ok(defined($ts->transflag([qw(JUSTDB)])), "Set transflags");
+warn ">> BEFORE SEGFAULT\n";
+#use MDK::Common 'backtrace';
+#*RPM4::Header::DESTROY = sub { warn ">> " . backtrace() };
 ok($ts->transrun(sub { my %a = @_; print STDERR "$a{what} $a{amount} / $a{total}\n" }) == 0, "Running transaction justdb");
+warn ">> AFTER SEGFAULT\n";
 
 my $found = 0;
 my $roffset;


More information about the Rpm-maint mailing list