develooper Front page | perl.perl5.porters | Postings from February 2020

Re: Bug in format introduced in 5.27.6

Thread Previous
From:
Dave Mitchell
Date:
February 4, 2020 12:51
Subject:
Re: Bug in format introduced in 5.27.6
Message ID:
20200204125122.GF4848@iabyn.com
On Tue, Jan 21, 2020 at 01:05:50PM +0100, H.Merijn Brand wrote:
> On Tue, 21 Jan 2020 12:49:16 +0100, "H.Merijn Brand"
> <h.m.brand@xs4all.nl> wrote:
> 
> > perl -le '$~ = "L02"; { local $~ = "$~h"; print $~; }'
> 
> FWIW, same for
>   perl -le '$~ = "L02"; { local $~ = $~."h"; print $~; }'
> 
> I had to assign $~ to a lexical for the workaround
> 
>   perl -le '$~ = "L02"; { my $f = $~; local $~ = $f."h"; print $~; }'
> 
> > up to and including perl-5.27.5, this would print "L02h"
> > as of 5.27.6 this prints "h"
> > 
> > this breaks production code :(

Fixed with the following commit. Note that localising magic vars has
always been a bit problematic. For example, the following fails on all
perls:

    $~ = "FOO";
    local $~ = $~;
    print "[$~]\n";  # prints "[]"

'local $~ = "....$~...."' works only because the RHS is an expression
which returns a temporary value which doesn't change when $~ is changed by
the localization.



commit d5a02d973b44832f918778202d68f066c8af3963
Author:     David Mitchell <davem@iabyn.com>
AuthorDate: Tue Feb 4 12:23:26 2020 +0000
Commit:     David Mitchell <davem@iabyn.com>
CommitDate: Tue Feb 4 12:43:24 2020 +0000

    multiconcat: keep assign for 'local $foo = "..."'
    
    In something like
    
        local $~ = "$~X";
    
    i.e. where localising a magic variable whose previous value should be
    used as part of a string concat on the RHS, don't fold the assign into
    the multiconcat op. Otherwise the code execution path looks a bit like:
    
        local($~) = undef;
        multiconcat($~, $~, "X");
    
    [ where multiconcat's args are (target, arg1, arg2,....) ]
    and thus multiconcat sees an undef arg.
    
    By leaving the assign out of the multiconcat, code execution now looks
    like
        my $targ;
        multiconcat($targ, $~, "X");
        local($~) = $targ;
    
    See http://nntp.perl.org/group/perl.perl5.porters/256898,
        "Bug in format introduced in 5.27.6".
    
    Although the bug only appears with magic vars, this patch pessimises
    all forms of 'local $foo = "..."', 'local $foo{bar} = "..."' etc.
    Strictly speaking the bug occurs because with 'local' you end up with
    two SVs (the saved one and the one currently in the glob) which both
    have the same container magic and where mg_set()ing one changes the
    mg_get() value of the other. Thus, vars like $!. One of the two SVs
    becomes an arg of multiconcat, the other becomes its target. Part of
    localising the target SV (before multiconcat is called) wipes the value
    of the arg SV.



-- 
Fire extinguisher (n) a device for holding open fire doors.

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About