Description
Description
Yes, this is contrived, but say I have something like: my $line = "123"; $line =~ s/ (.*) / foo($1) /e;
i.e., Assign $line
, then substitute its contents with the results of foo(...)
Now let's say foo()
looks like:
sub foo {
die "Not A Whole Number" unless $_[0] =~ /^\d+$/; # Guard
# Else...
my $num = shift; # or my ($num, $arg, $platypus) = @_; or whatever...
warn "Doing fancy stuff with num=$num\n";
999 - $num; # Super Fancy Stuff...
}
When called, Perl aliases the first argument — in this case, the $1
capture from the s///e regex — to the first element of @_
. Then, the regex in the guard matches, and since it has no captures, it clears $1
... But that's the same $1
that's aliased in $_[0]
, so now the first element of our argument list becomes undef... «sad»
Steps to Reproduce
perl -E 'sub foo { $_[0] }; say "OK" =~ s/(.*)/ foo($1) /er' # OKAY
perl -E 'sub foo { m//; $_[0] }; say "OK" =~ s/(.*)/ foo($1) /er' # FAIL!
perl -E 'sub foo { m//; $_[0] }; say "OK" =~ s/(.*)/ foo("$1") /er' # OKAY
perl -E 'sub foo { m//; $_[0] }; say "OK" =~ s/(.*)/ foo( my $x = $1 ) /er' # OKAY
perl -E 'sub foo { m//; $_[0] }; say "OK" =~ s/(.*)/ $_ = $1; foo($_) /er' # OKAY
perl -E 'sub foo (_) { m//; $_[0] }; say "OK" =~ s/(.*)/ $_ = $1; foo /er' # OKAY
perl -E 'sub foo { @_ = @_; m//; $_[0] }; say "OK" =~ s/(.*)/ foo($1) /er' # 😒 OK
perl -E 'sub foo { m//; $_[0] }; say foo("OK")' # OKAY, not in s///e
Also:
docker run --rm -it perl:5.40.2 perl -E 'sub foo { m//; $_[0] }; say "OK" =~ s/(.*)/ foo($1) /er' # FAIL!
Expected behavior
I would expect @_
to receive a copy of $1
(et al) with pass-by-value semantics, not by-reference (especially since it's non-modifiable, anyway...)
Perl configuration
Stock /usr/bin/perl
on MacOS 15.5 Sequoia
Summary of my perl5 (revision 5 version 34 subversion 1) configuration:
Platform:
osname=darwin
osvers=24.0
archname=darwin-thread-multi-2level
uname='darwin ln86f.p1s.plx.sd.apple.com 24.0 darwin kernel version 23.0.0: thu feb 1 13:18:34 pst 2024; root:xnu-10002.1.11.100.4~1development_x86_64 x86_64 '
config_args='-ds -e -Dprefix=/usr -Dccflags=-g -pipe -Dldflags= -Dman3ext=3pm -Duseithreads -Duseshrplib -Dinc_version_list=none -Dcc=cc'
hint=recommended
useposix=true
d_sigaction=define
useithreads=define
usemultiplicity=define
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
Compiler:
cc='cc'
ccflags =' -g -pipe -fno-strict-aliasing -fstack-protector-strong -DPERL_USE_SAFE_PUTENV'
optimize='-Os'
cppflags='-g -pipe -fno-strict-aliasing -fstack-protector-strong'
ccversion=''
gccversion='Apple LLVM 17.0.0 (clang-1700.0.13.5) [+internal-os]'
gccosandvers=''
intsize=4
longsize=8
ptrsize=8
doublesize=8
byteorder=12345678
doublekind=3
d_longlong=define
longlongsize=8
d_longdbl=define
longdblsize=16
longdblkind=3
ivtype='long'
ivsize=8
nvtype='double'
nvsize=8
Off_t='off_t'
lseeksize=8
alignbytes=8
prototype=define
Linker and Libraries:
ld='cc'
ldflags =' -fstack-protector-strong'
libpth=/AppleInternal/Library/BuildRoots/1c8f7852-1ca9-11f0-b28b-226177e5bb69/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.Internal.sdk/usr/local/lib /AppleInternal/Library/BuildRoots/1c8f7852-1ca9-11f0-b28b-226177e5bb69/Applications/Xcode.app/Contents/Developer/Toolchains/OSX15.5.xctoolchain/usr/lib/clang/17/lib /AppleInternal/Library/BuildRoots/1c8f7852-1ca9-11f0-b28b-226177e5bb69/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.Internal.sdk/usr/lib /AppleInternal/Library/BuildRoots/1c8f7852-1ca9-11f0-b28b-226177e5bb69/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /usr/lib /usr/local/lib
libs=
perllibs=
libc=
so=dylib
useshrplib=true
libperl=libperl.dylib
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=bundle
d_dlsymun=undef
ccdlflags=' '
cccdlflags=' '
lddlflags=' -bundle -undefined dynamic_lookup -fstack-protector-strong'
Characteristics of this binary (from libperl):
Compile-time options:
HAS_TIMES
MULTIPLICITY
PERLIO_LAYERS
PERL_COPY_ON_WRITE
PERL_DONT_CREATE_GVSV
PERL_IMPLICIT_CONTEXT
PERL_MALLOC_WRAP
PERL_OP_PARENT
PERL_PRESERVE_IVUV
PERL_USE_SAFE_PUTENV
USE_64_BIT_ALL
USE_64_BIT_INT
USE_ITHREADS
USE_LARGE_FILES
USE_LOCALE
USE_LOCALE_COLLATE
USE_LOCALE_CTYPE
USE_LOCALE_NUMERIC
USE_LOCALE_TIME
USE_PERLIO
USE_PERL_ATOF
USE_REENTRANT_API
USE_THREAD_SAFE_LOCALE
Locally applied patches:
/Library/Perl/Updates/<version> comes before system perl directories
installprivlib and installarchlib points to the Updates directory
Built under darwin
Compiled at Apr 18 2025 20:20:39
@INC:
/Library/Perl/5.34/darwin-thread-multi-2level
/Library/Perl/5.34
/Network/Library/Perl/5.34/darwin-thread-multi-2level
/Network/Library/Perl/5.34
/Library/Perl/Updates/5.34.1/darwin-thread-multi-2level
/Library/Perl/Updates/5.34.1
/System/Library/Perl/5.34/darwin-thread-multi-2level
/System/Library/Perl/5.34
/System/Library/Perl/Extras/5.34/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.34