This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
av_fetch(): remove check for freed SV
authorDavid Mitchell <davem@iabyn.com>
Fri, 19 Aug 2016 10:39:20 +0000 (11:39 +0100)
committerDavid Mitchell <davem@iabyn.com>
Fri, 19 Aug 2016 10:44:58 +0000 (11:44 +0100)
Currently av_fetch() has this extra test:

    if (AvREIFY(av) && SvIS_FREED(AvARRAY(av)[key])) {
        /* eg. @_ could have freed elts */
        AvARRAY(av)[key] = NULL;        /* 1/2 reify */

which basically says that if the array has the reify flag set (typically
only @_ has this) and if the element being retrieved in it has been freed,
then replace it with an undef value instead.

This can be triggered with code like:

    sub f {
        $r = 0;
        my $var = $_[0];
    }

    $r = do { my $x; \$x };
    f($$r);

which leaves $var as undef rather than causing a "panic: attempt to copy
freed scalar".

However, code like

    my ($var) = @_;

*won't* get handled specially, and will still trigger the panic.

It was added in 1996 as a result of this thread:

    From: Andreas Koenig <k@anna.in-berlin.de>
    Subject: SEGV with $_[0] and circular references
    Message-Id: <199608131528.RAA25965@anna.in-berlin.de>

That was in the context of getting a SEGV - whereas now we get the
"panic: attempt to copy freed scalar" instead.

It was agreed in this thread that it could be removed:

    http://nntp.perl.org/group/perl.perl5.porters/239082

av.c
pp_hot.c

diff --git a/av.c b/av.c
index 8f8cda5..21828a9 100644 (file)
--- a/av.c
+++ b/av.c
@@ -288,11 +288,6 @@ Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval)
        return lval ? av_store(av,key,newSV(0)) : NULL;
     }
 
-    if (UNLIKELY(AvREIFY(av) && SvIS_FREED(AvARRAY(av)[key]))) {
-       /* eg. @_ could have freed elts */
-       AvARRAY(av)[key] = NULL;        /* 1/2 reify */
-       goto emptyness;
-    }
     return &AvARRAY(av)[key];
 }
 
index 3f37ce4..a794fd5 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -830,7 +830,7 @@ PP(pp_aelemfast)
     /* inlined av_fetch() for simple cases ... */
     if (!SvRMAGICAL(av) && key >= 0 && key <= AvFILLp(av)) {
         sv = AvARRAY(av)[key];
-        if (sv && !SvIS_FREED(sv)) {
+        if (sv) {
             PUSHs(sv);
             RETURN;
         }