Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpectedly autovivifies an arrayref under specific conditions #19391

Closed
yahermann opened this issue Feb 4, 2022 · 7 comments
Closed

Unexpectedly autovivifies an arrayref under specific conditions #19391

yahermann opened this issue Feb 4, 2022 · 7 comments

Comments

@yahermann
Copy link

yahermann commented Feb 4, 2022

This is a bug report for perl from hermann@jovial.org,
generated with the help of perlbug 1.40 running under perl 5.26.2.


[Please describe your issue here]

Under specific conditions as described below, Perl appears to autovivify an arrayref instead of reporting the expected error, "Can't use an undefined value as an ARRAY reference". Here is a test:

use Test2::V0;

my $hashref = {};

my $dispatch = {
  choice => [ map {$_} @{ $hashref->{'something'} } ]
};

is( ref($hashref->{'something'}), '' );   # hashref->{'something'} becomes []

done_testing();

If we change above to:

my $dispatch = {
  choice => [ @{ $hashref->{'something'} } ]     # removed map{$_}
};

then we get the expected "Can't use an undefined value as an ARRAY reference" error.

[Please do not change anything below this line]


Flags:
category=core
severity=medium

Site configuration information for perl 5.26.2:

Configured by hermann at Tue Nov 6 23:24:34 UTC 2018.

Summary of my perl5 (revision 5 version 26 subversion 2) configuration:

Platform:
osname=linux
osvers=4.15.0-38-generic
archname=x86_64-linux
uname='linux magnolia 4.15.0-38-generic #41-ubuntu smp wed oct 10 10:59:38 utc 2018 x86_64 x86_64 x86_64 gnulinux '
config_args='-de -Dprefix=/home/hermann/perl5/perlbrew/perls/perl-5.26.2 -Aeval:scriptdir=/home/hermann/perl5/perlbrew/perls/perl-5.26.2/bin'
hint=recommended
useposix=true
d_sigaction=define
useithreads=undef
usemultiplicity=undef
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
bincompat5005=undef
Compiler:
cc='cc'
ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
optimize='-O2'
cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='7.3.0'
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 -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
libc=libc-2.27.so
so=so
useshrplib=false
libperl=libperl.a
gnulibc_version='2.27'
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-E'
cccdlflags='-fPIC'
lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Locally applied patches:
Devel::PatchPerl 1.52


@inc for perl 5.26.2:
/home/hermann/perl5/perlbrew/perls/perl-5.26.2/lib/site_perl/5.26.2/x86_64-linux
/home/hermann/perl5/perlbrew/perls/perl-5.26.2/lib/site_perl/5.26.2
/home/hermann/perl5/perlbrew/perls/perl-5.26.2/lib/5.26.2/x86_64-linux
/home/hermann/perl5/perlbrew/perls/perl-5.26.2/lib/5.26.2


Environment for perl 5.26.2:
HOME=/home/hermann
LANG=en_US.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/hermann/perl5/perlbrew/bin:/home/hermann/perl5/perlbrew/perls/perl-5.26.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
PERLBREW_HOME=/home/hermann/.perlbrew
PERLBREW_MANPATH=/home/hermann/perl5/perlbrew/perls/perl-5.26.2/man
PERLBREW_PATH=/home/hermann/perl5/perlbrew/bin:/home/hermann/perl5/perlbrew/perls/perl-5.26.2/bin
PERLBREW_PERL=perl-5.26.2
PERLBREW_ROOT=/home/hermann/perl5/perlbrew
PERLBREW_SHELLRC_VERSION=0.84
PERLBREW_VERSION=0.84
PERL_BADLANG (unset)
SHELL=/bin/bash

@Grinnz
Copy link
Contributor

Grinnz commented Feb 4, 2022

This is sort of expected (I think), as map provides an lvalue context to the dereference.

@yahermann
Copy link
Author

yahermann commented Feb 4, 2022

I wouldn't expect $hashref->{'something'} to be mutated. I would expect an array to be created from @{ $hashref->{'something'} }, however because $hashref->{'something'} is undef, I would expect an error at that point, before the map.

@yahermann
Copy link
Author

yahermann commented Feb 4, 2022

Here's a more direct test:

my $undef = undef;

my @array1 = @{ $undef };  # error: Can't use an undefined value as an ARRAY reference

my @array2 = map {$_} @{ $undef };
is( ref($undef), '' );   # 'ARRAY'  ($undef is now [])

I guess what I would expect in the 2nd case, is that Perl would generate the error before map is even relevant.

@Grinnz
Copy link
Contributor

Grinnz commented Feb 4, 2022

That's what I mean by "sort of" expected. It's how lvalue context works, but lvalue context is pretty unintuitive. Essentially when in lvalue context, it disables that error and the SV is allowed to autovivify to an arrayref, the same thing that happens if you would do @$foo = 1..10;

@Grinnz
Copy link
Contributor

Grinnz commented Feb 4, 2022

And it happens in map because map allows mutation of its arguments via alias, though this is not good practice.

@yahermann
Copy link
Author

Thanks for the explanation. Yeah, I know map can mutate each element (which I agree is not a good practice), I just didn't expect it to create an arrayref from thin air as well (also not a best practice, imho).

We'll have to chalk this one up to Perl being Perl :-).

Feel free to close this out, have a great weekend!

@jkeenan
Copy link
Contributor

jkeenan commented Feb 4, 2022

Closing per OP request.

@jkeenan jkeenan closed this as completed Feb 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants