[Perl/perl5] 3364ec: find_lexical_cv: fix following the parent indexes ...

[email protected] (Tony Cook via perl5-changes)
Newsgroups perl.perl5.changes
Message-ID <Perl/perl5/push/refs/heads/blead/[email protected]>
  Branch: refs/heads/blead
  Home:   https://github.com/Perl/perl5
  Commit: 3364ec30b83a92c7135acbc44b80f7fd8858131d
      https://github.com/Perl/perl5/commit/3364ec30b83a92c7135acbc44b80f7fd8858131d
  Author: Tony Cook <[email protected]>
  Date:   2026-03-25 (Wed, 25 Mar 2026)

  Changed paths:
    M op.c
    M t/op/lexsub.t

  Log Message:
  -----------
  find_lexical_cv: fix following the parent indexes after a gap

Normally padvars inherited from outer scopes have a PARENT_PAD_INDEX()
value that is that names index in the outer scope, found by
CvOUTSIDE().

So imagine these pads, each for an enclosing scope:

  [&true] [&reftype] [&foo] [&bar]  # outer most scope
  [&true PPI=1] [&reftype PPI=2]    # A scope
  [&true PPI=1]                     # B scope

where PPI is the PARENT_PAD_INDEX() for that entry, so the B scope
inherits "&true" from index 1 in the A scope, and A inherits "&true"
from index 1 and "&reftype" from index 2 in the outermost scope.

This might correspond to code like:

  # definitions of true, reftype, foo, bar
  use builtin qw(true reftype);
  my sub foo { ... }
  my sub bar { ... }

  sub A {
    # inherited references to reftype and true
    if (reftype($somevar) eq "HASH" && ...)
       return true;

     my sub B {
       eval "... reftype(...) ...";
       return true;
     }
  }

The pad cannot be modified after the sub has finished compilation.

So if we do an eval within the B scope and reference &reftype:

  [&true] [&reftype] [&foo] [&bar]  # outer most scope
  [&true PPI=1] [&reftype PPI=2]    # A scope
  [$y] [&true PPI=2]                # B scope
  [&reftype]                        # eval scope

we can no longer modify scope B to build the PARENT_PAD_INDEX chain up
to the original imported definition.

Before b0bc598140d4 this could result in an assertion or segmentation
fault, since find_lexical_cv() didn't handle the gap in the chain at
all.

The fix in b0bc598140d4 handled the case where the name was found
after the gap in the defining scope, this allows find_lexical_cv() to
correctly find &foo or &bar starting from the eval scope, but it
didn't correctly adjust the working pad index when that name was
inherited from some parent scope, such as &reftype in A being
inherited from the outer most scope.

So for &reftype, the starting index is 1, find_lexical_cv() sees the
missing index, does an exhaustive search up the CvOUTSIDE() chain and
finds it in the A scope, but didn't adjust the index to the found
entry 2, this meant it started following the chain from the &true
entry, resulting it finding the CV for &true and failing to compile
since the prototype for &true allows no arguments, unlike &reftype.

This change fixes that, so when the name is found after the break in
the PARENT_PAD_INDEX chain, the index starts from the correct pad
entry.

Fixes #24131
Fixes #24056


  Commit: a26628aaf68b64f792c1f02d8400cd2f7ce93084
      https://github.com/Perl/perl5/commit/a26628aaf68b64f792c1f02d8400cd2f7ce93084
  Author: Tony Cook <[email protected]>
  Date:   2026-03-25 (Wed, 25 Mar 2026)

  Changed paths:
    M pod/perldelta.pod

  Log Message:
  -----------
  perldelta for find_lexical_sv() finding the wrong sub


Compare: https://github.com/Perl/perl5/compare/a76201055098...a26628aaf68b

To unsubscribe from these emails, change your notification settings at https://github.com/Perl/perl5/settings/notifications
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.