Package: perl
Version: 5.38.0-1
Severity: important
Tags: upstream
User: debian-p...@lists.debian.org
Usertags: perl-5.38-transition
Control: affects -1 libhtml-widget-perl

The libhtml-widget-perl package fails to build with Perl 5.38 on
perl.debian.net:

  
http://perl.debian.net/rebuild-logs/perl-5.38-throwaway/libhtml-widget-perl_1.11-6/libhtml-widget-perl_1.11-6_amd64-2023-08-09T09:20:08Z.build

   #   Failed test 'use HTML::Widget;'
   #   at t/01use.t line 6.
   #     Tried to use 'HTML::Widget'.
   #     Error:  Use of freed value in iteration at 
/usr/share/perl5/Module/Pluggable/Fast.pm line 74.
   # Compilation failed in require at t/01use.t line 6.
   # BEGIN failed--compilation aborted at t/01use.t line 6.
   # Looks like you failed 1 test of 1.

   [...]
 
The build fails deterministically every time on that host, but not on
my local workstation (and neither on Gregor's according to his report on
IRC.) It also fails if I run the test suite manually on perl.debian.net.

After a few nights of glaring at this, I think it's probably an instance
of the longstanding stack-not-refcounted issue (see #582925) and has
been present ever since '.' was removed from the default @INC and base.pm
acquired the "dotless-INC guard" in

https://github.com/Perl/perl5/commit/fa71f6670dda393818d17f2f3bd2bee165347849

As I understand it, Module::Pluggable::Fast is looping over @INC and
ends up calling base.pm which fiddles with @INC under the hood if
it contains cwd (dot). This results in rather undefined behaviour,
sometimes triggering the fatal "Use of freed value in iteration" error.

The undefined behaviour is very sensitive to @INC contents and
length, making this something of a heisenbug. It's easier to trigger with
Perl 5.38 than earlier versions but that's probably just by chance.

I'm able to trigger it in the HTML-Widget build on my local workstation
with Perl 5.38 by running "PERL5LIB=.:. make test". It also triggers on
sid / Perl 5.36 both on my workstation and perl.debian.net with something
silly like

  PERL5LIB=$(perl -e "print 'x:'x40")x make test

The HTML-Widget build runs the test suite with Test::Harness, which
sets PERL_USE_UNSAFE_INC=1, putting cwd on @INC and activating the
base.pm guard.  A workaround seems to be explicitly running
  PERL_USE_UNSAFE_INC=0 make test
as Test::Harness respects that. This does make libhtml-widget-perl
test suite pass me on perl.debian.net with Perl 5.38, so maybe it
can be used to mitigate the immediate issue in Debian.

I was able to narrow the thing down to this test case, which fails
deterministically everywhere I've tried, with every Perl version since
the dot-on-INC removal including current upstream bleadperl:

   % tree
   .
   |-- lib
   |   `-- Plugins
   |       `-- B.pm
   `-- test.t
   
   3 directories, 2 files
   % cat test.t
   #!/usr/bin/perl
   BEGIN { print "1..3\n"; }
   
   push @INC, './lib'; # plugin path
   push @INC, '.';     # needed to trigger 'Use of freed value in iteration'
   
   package MyPlugin;
   sub new { print "ok 1 - new() called for plugin $_[0]\n"; }
   1;
   
   package A;
   use Module::Pluggable::Fast search => [qw/Plugins/];
   print scalar A->plugins ?
           "ok 2 - found plugins\n" :
           "not ok 2 - no plugins found\n";
   1;
   
   print "ok 3 - all done\n";
   % cat lib/Plugins/B.pm
   package Plugins::B;
   use base qw/MyPlugin/;
   1;
   % /opt/perl/bin/perl5.39.2 test.t
   1..3
   ok 1 - new() called for plugin Plugins::B
   Use of freed value in iteration at 
/opt/perl/lib/site_perl/5.39.2/Module/Pluggable/Fast.pm line 74.

 
and further down to this, which is sillier but more self contained as
it only uses base.pm:

   % cat test2.t
   BEGIN { print "1..1\n"; }
   
   package X;
   sub x { }
   1;
   
   package main;
   require base;
   
   push @INC, '.';
   foreach my $dir ( grep /./, @INC) 
   {
           base->import('X');
   }
   
   print "ok 1\n";
   % /opt/perl/bin/perl5.39.2 test2.t
   1..1
   Use of freed value in iteration at test2.t line 13.

This whole wall of text should be reported upstream too. Things are
complicated a bit by the fact that HTML-Widget, which prominently exhibits
this behaviour, is dead upstream and rather heavily patched in Debian
to make it able to build at all. But maybe the shorter test case with
Module::Pluggable::Fast is enough to show it's an actual issue.

-- 
Niko

Reply via email to