Index | Thread | Search

From:
James Cook <falsifian@falsifian.org>
Subject:
[patch] Re: OpenBSD perl 5.42.0 - Call for Testing
To:
Andrew Hewus Fresh <andrew@afresh1.com>
Cc:
tech@openbsd.org
Date:
Sat, 03 Jan 2026 17:29:03 +0000

Download raw body.

Thread
Andrew Hewus Fresh <andrew@afresh1.com> wrote:
> Yet another perl update, this time to 5.42.0.  There is talk about a .1
> release, but it didn't sound like anything that should block this update.

There is a regression in 5.42.0: a segfault which is fairly easy to
encounter. Here is a simple way to trigger it:

	perl -c -wE 'for my ($x, $y) (Bar->foo) {}'

This causes perl 5.42.0 to segfault. Perl 5.40.0 says "-e syntax OK".

I've included the upstream fix as a patch. I would be grateful if it
could be included in the next OpenBSD release.

The problem is documented here: https://github.com/perl/perl5/issues/23405
The below patch is upstream commit 96673a4b, which (when I asked in October)
people on #perl in libera.chat thought was a reasonable thing to apply to
5.40.0.

It is perhaps worth noting that the October perl5-porters mailing list
post about a 5.42.1 maintenance release suggested it would be worth it
even if it only included that commit.

Although I have only minimally tested this on OpenBSD, I can say
that on NetBSD, the full perl test suite passed when I applied that
same change to the 5.40.0 source (and it's the patch is in pkgsrc).

(BTW, is there a reliable way to build/test only gnu/usr.bin/perl in
OpenBSD's source tree? In order to test this patch, I just followed the
release(8) instructions excluding xenocara, which feels like overkill,
but I didn't want to make assumptions (e.g: I can just follow perl's
build instructions) or spend too much time digging into the build
system internals.)

-- 
James

diff /usr/src
path + /usr/src
commit - 287000ffa12fe34ef71791da513207ea48a4b740
blob - f616532c491cebc2d5dc89f124135ff4a9841281
file + gnu/usr.bin/perl/op.c
--- gnu/usr.bin/perl/op.c
+++ gnu/usr.bin/perl/op.c
@@ -9665,7 +9665,7 @@ S_op_is_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
         }
 
         case OP_PADCV:
-            cv = (CV *)PAD_SVl(o->op_targ);
+            cv = find_lexical_cv(o->op_targ);
             assert(cv && SvTYPE(cv) == SVt_PVCV);
             break;
 
@@ -9683,10 +9683,18 @@ S_op_is_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
 static bool
 S_op_is_call_to_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
 {
-    if(o->op_type != OP_ENTERSUB)
+    if (o->op_type != OP_ENTERSUB)
         return false;
 
-    OP *cvop = cLISTOPx(cUNOPo->op_first)->op_last;
+    /* entersub may be a UNOP, not a LISTOP, so we can't just use op_last */
+    OP *aop = cUNOPo->op_first;
+    if (!OpHAS_SIBLING(aop)) {
+        aop = cUNOPx(aop)->op_first;
+    }
+    aop = OpSIBLING(aop);
+    OP *cvop;
+    for (cvop = aop; OpHAS_SIBLING(cvop); cvop = OpSIBLING(cvop)) ;
+
     return op_is_cv_xsub(cvop, xsub);
 }
 
commit - 287000ffa12fe34ef71791da513207ea48a4b740
blob - 2f6790aee7758e16c2c86374648e22a9304ca4fe
file + gnu/usr.bin/perl/t/op/for-many.t
--- gnu/usr.bin/perl/t/op/for-many.t
+++ gnu/usr.bin/perl/t/op/for-many.t
@@ -498,4 +498,17 @@ is($continue, 'xx', 'continue reached twice');
     is("@have", "Pointy end Up Flamey end Down", 'for my ($one, $two)');
 }
 
+# GH #23405 - segfaults when compiling 2-var for loops
+{
+    my $dummy = sub {};
+    for my ($x, $y) (main->$dummy) {}
+    pass '2-var for does not crash on method calls';
+
+    my sub dummy {}
+    sub {
+        for my ($x, $y) (dummy) {}
+    }->();
+    pass '2-var for does not crash on lexical sub calls';
+}
+
 done_testing();