Closed p5pRT closed 21 years ago
I have encountered a bug that involves the changing of scope. Here is some sample code that demonstrates the problem.
\
1 #!/usr/bin/perl -w 2 3 $x = "outer-scope"; 4 5 { 6 my $x = "inner-scope"; 7 print "$x[R0]" . "\n"; 8 print "${x}[R0]" . "\n"; 9 print "${x} [R0]" . "\n"; 10 }
\
Results: Argument "R0" isn't numeric in aelem at ./test.pl line 7. Use of uninitialized value at ./test.pl line 7.
outer-scope[R0] inner-scope [R0]
Line 8 should either print an error because it is expecting an array\, as line 7 did\, or else it should give ${x} as the local value. Instead it prints the outer scoped variable.
There are many variations of this that can be reproduced\, but this is a basic example. The easy work-around is to escape the brackets around 'R0'.
Dustin Jones (via RT) \perlbug\-followup@​perl\.org wrote:
I have encountered a bug that involves the changing of scope. Here is some sample code that demonstrates the problem.
Here's a cut-down version :
my $x = 'x'; print "${x}{"; print "${x}["; print "\n";
This simply prints '{['.
Somehow the qq lexer doesn't see lexicals in this case.
Summary of my perl5 (5.0 patchlevel 5 subversion 3) configuration:
This bug is present in 5.6.x\, 5.8.0 and in blead.
On Wed\, Feb 05\, 2003 at 10:06:53AM +0100\, Rafael Garcia-Suarez wrote:
Here's a cut-down version :
my $x = 'x'; print "$\{x\}\{"; print "$\{x\}\["; print "\\n";
This simply prints '{['.
this little hack fixes it:
Setting PL_expect to XREF will prevent Perl from searching for '%x' or '@x' instead of '$x' in pad_findmy() and\, not finding it\, generate a 'gvsv' OP instead of a 'padsv' OP\, as it should. (see toke.c :3461 :3557 :5288)
It's otherwise harmless - PL_expect will be set to XOPERATOR anyway.
Here is a test script:
#! /usr/bin/perl use Test::More tests => 3; { undef $a; undef @b; my $a="a"; ok("${a}{" eq "a{"); my $a="a"; ok("${a}[" eq "a["); my @b=("b"); ok("@{b}{" eq "b{"); } __END__
Regards Adi
arthur@contiller.se - Status changed from 'new' to 'open'
Hi\,
This bug has now been closed as the patch from Enache Adrian was applied as change 18687 to bleadperl.
Arthur
arthur@contiller.se - Status changed from 'open' to 'resolved'
Rafael Garcia-Suarez \rgarciasuarez@​free\.fr wrote: :Dustin Jones (via RT) \perlbug\-followup@​perl\.org wrote: :> I have encountered a bug that involves the changing of scope. :> Here is some sample code that demonstrates the problem. : :Here's a cut-down version : : : my $x = 'x'; : print "${x}{"; : print "${x}["; : print "\n"; : :This simply prints '{['. : :Somehow the qq lexer doesn't see lexicals in this case.
I think I looked at this a couple of years ago\, and got stuck. If I remember rightly\, cleverness in toke.c sees the '[' and modifies the token buffer to '@{x}'; later it knows @x is not a lexical\, so doesn't upgrade it to a pad lookup; and then later still it releases that the '[' didn't introduce a dereference\, and fixes up the resulting op to find the scalar ::$x rather than ::@x.
Some of the details may be wrong\, but this bit is right: it's a whole hairy mess\, and should get its darned hair cut.
Hugo
On onsdag\, feb 12\, 2003\, at 05:43 Europe/Stockholm\, hv@crypt.org wrote:
ubject: Re: [perl #20716] scope error with brackets
Rafael Garcia-Suarez \rgarciasuarez@​free\.fr wrote: :Dustin Jones (via RT) \perlbug\-followup@​perl\.org wrote: :> I have encountered a bug that involves the changing of scope. :> Here is some sample code that demonstrates the problem. : :Here's a cut-down version : : : my $x = 'x'; : print "${x}{"; : print "${x}["; : print "\n"; : :This simply prints '{['. : :Somehow the qq lexer doesn't see lexicals in this case.
I think I looked at this a couple of years ago\, and got stuck. If I remember rightly\, cleverness in toke.c sees the '[' and modifies the token buffer to '@{x}'; later it knows @x is not a lexical\, so doesn't upgrade it to a pad lookup; and then later still it releases that the '[' didn't introduce a dereference\, and fixes up the resulting op to find the scalar ::$x rather than ::@x.
Some of the details may be wrong\, but this bit is right: it's a whole hairy mess\, and should get its darned hair cut.
Hugo
I applied patch 18687 from Enache Adrian that fixed this problem\, was the patch incorrect?
Arthur
A.Bergman \sky@​nanisky\.com wrote:
I applied patch 18687 from Enache Adrian that fixed this problem\, was the patch incorrect?
I was also going to apply this one\, this patch looks (partially) correct to me. Except that it doesn't solve the similar bug with qr{} -- probably the only thing that's needed is to test for PL_lex_inwhat == OP_QR as well.
On Wed\, Feb 12\, 2003 at 09:50:32AM +0100\, Rafael Garcia-Suarez wrote:
A.Bergman \sky@​nanisky\.com wrote:
I applied patch 18687 from Enache Adrian that fixed this problem\, was the patch incorrect?
I was also going to apply this one\, this patch looks (partially) correct to me. Except that it doesn't solve the similar bug with qr{} -- probably the only thing that's needed is to test for PL_lex_inwhat == OP_QR as well.
I could swear intuit_more() was already handling this :-)
Regards Adi
Enache Adrian wrote:
--- /arc/perl-current/toke.c 2003-02-10 21:23:38.000000000 +0200 +++ perl-current/toke.c 2003-02-12 21:18:42.000000000 +0200 @@ -6287\,7 +6287\,7 @@ S_scan_ident(pTHX_ register char *s\, reg funny\, dest\, funny\, dest); } } - if (PL_lex_inwhat == OP_STRINGIFY) + if (PL_lex_inwhat == OP_STRINGIFY || PL_lex_inwhat == OP_MATCH)
Nope\, I think you'll need OP_QR at least also for the case qr/${x}{/.
Note that Arthur added regression tests when he applied your patch (to t/comp/parser.t\, see change #18687). Could you do the same for m// and qr// ? and s/// ? and possibly with qx// ? (and I think we're done with interpolation contexts) (although it's arguably difficult to add portable tests that use qx//\, esp. in a t/comp/ test\, which is aimed at testing the basic parsing techniques)
On Wed\, Feb 12\, 2003 at 10:01:46PM +0100\, Rafael Garcia-Suarez wrote:
Enache Adrian wrote:
--- /arc/perl-current/toke.c 2003-02-10 21:23:38.000000000 +0200 +++ perl-current/toke.c 2003-02-12 21:18:42.000000000 +0200 @@ -6287\,7 +6287\,7 @@ S_scan_ident(pTHX_ register char *s\, reg funny\, dest\, funny\, dest); } } - if (PL_lex_inwhat == OP_STRINGIFY) + if (PL_lex_inwhat == OP_STRINGIFY || PL_lex_inwhat == OP_MATCH)
Nope\, I think you'll need OP_QR at least also for the case qr/${x}{/.
I thinked the same\, but:
\(gdb\) r \-e 'my $p=1;print qr\($\{p\}\{\)'
\.\.\.\.
\(gdb\) br toke\.c​:6289
Breakpoint 2 at 0x40056a27​: file toke\.c\, line 6289\.
\(gdb\) cont
Breakpoint 2\, S\_scan\_ident \(my\_perl=0x804bb58\, s=0x8064b64 "\{"\,
send=0x8064b65 ""\, dest=0x804c105 "p"\, destlen=5\, ck\_uni=0\) at toke\.c​:6290
6290 if \(PL\_lex\_inwhat == OP\_STRINGIFY || PL\_lex\_inwhat == OP\_MATCH\)
\(gdb\) p PL\_op\_name\[my\_perl\->Ilex\_inwhat\]
$1 = 0x4012dc9a "match"
\.\.\.\.
I added the OP_BACKTICK and OP_SUBST to my patch and it turned into something very ugly :-(. I'm still looking for a simpler solution ( maybe modifying intuit_more() ? )
Note that Arthur added regression tests when he applied your patch (to t/comp/parser.t\, see change #18687). Could you do the same for m// and qr// ? and s/// ? and possibly with qx// ? (and I think we're done with interpolation contexts) (although it's arguably difficult to add portable tests that use qx//\, esp. in a t/comp/ test\, which is aimed at testing the basic parsing techniques)
Maybe this should do:
#! /usr/bin/perl use Test::More tests => 10; { undef $a; undef @b;
my $a="a"; ok("${a}{" eq "a{"); my $a="a"; ok("${a}[" eq "a["); my @b=("b"); ok("@{b}{" eq "b{");
my $a="a"; ok(qx/echo ${a}{/ eq "a{\n"); my $a="a"; ok(qx/echo ${a}[/ eq "a[\n"); my @b=("b"); ok(qx/echo @{b}{/ eq "b{\n");
my $a="a"; ok("-a{-" =~ m/-${a}{-/); my @b=("b"); ok("-b{-" =~ m/-@{b}{-/);
my $a="a"; $_="-a{-"; s/${a}{/x/; ok($_ eq "-x-"); my @b=("b"); $_="-b{-"; s/@{b}{/x/; ok($_ eq "-x-"); } __END__
With my patch applied\, I just passed all tests on my FreeBSD-current box.
Regards Adi
On Thu\, Feb 13\, 2003 at 01:02:03AM +0200\, Enache Adrian wrote:
I thinked the same\, but:
Sorry for my english!
my $a="a"; $\_="\-a\{\-"; s/$\{a\}\{/x/; ok\($\_ eq "\-x\-"\); my @​b=\("b"\); $\_="\-b\{\-"; s/@​\{b\}\{/x/; ok\($\_ eq "\-x\-"\);
}
Maybe add these tests too ?
my $a="a"; $_="-x-"; s/x/${a}{/; ok($_ eq "-a{-"); my @b=("b"); $_="-x-"; s/x/@{b}{/; ok($_ eq "-b{-");
Regards Adi
On Wed\, Feb 12\, 2003 at 10:01:46PM +0100\, Rafael Garcia-Suarez wrote:
Enache Adrian wrote:
--- /arc/perl-current/toke.c 2003-02-10 21:23:38.000000000 +0200 +++ perl-current/toke.c 2003-02-12 21:18:42.000000000 +0200 @@ -6287\,7 +6287\,7 @@ S_scan_ident(pTHX_ register char *s\, reg funny\, dest\, funny\, dest); } } - if (PL_lex_inwhat == OP_STRINGIFY) + if (PL_lex_inwhat == OP_STRINGIFY || PL_lex_inwhat == OP_MATCH)
Sorry for the false noise. Making a lot of tests for all possible cases (OP_MATCH\, OP_BACKTICK\, OP_SUBST\, etc) was really stupid.
I hope I get it right finally with this very simple solution. ( passes all tests for me on FreeBSD & linux systems ). Please try.
Note that Arthur added regression tests when he applied your patch (to t/comp/parser.t\, see change #18687). Could you do the same for m// and qr// ? and s/// ? and possibly with qx// ? (and I think we're done with interpolation contexts) (although it's arguably difficult to add portable tests that use qx//\, esp. in a t/comp/ test\, which is aimed at testing the basic parsing techniques)
Here is a more complete test script. It tests for qq//\,qx//\,qr//\, s/// and also for heredoc interpolation. The qx/echo ../ trick should work on Windows too. ( I know nothing about VMS\, etc ).
#! /usr/bin/perl use Test::More tests => 6; { undef $a; undef @b;
my $a="a"; my @b="b"; my @a="z"; ok(qq/${a}{ ${a}[ @{b}{/ eq "a{ a[ b{");
ok("-a{-a1-b{-" =~ qr/-${a}{-${a}[1]-@{b}{-/);
ok(qx/echo ${a}{ ${a}[ @{b}{/ eq "a{ a[ b{\n");
ok(\<\<END eq "a{ a[ b{\n"); ${a}{ ${a}[ @{b}{ END
$_ = "-a{-a1-b{-"; s/${a}[1]/x/; s/${a}{/x/; s/@{b}{/x/; ok($_ eq "-x-x-x-");
$_="-x-x-x-"; s/x/${a}{/; s/x/${a}[/; s/x/@{b}{/; ok($_ eq "-a{-a[-b{-");
} __END__
Note: I seems to be no difference between qr// and m// from the variable interpolation point of view.
Regards Adi
"A. Bergman" \sky@​nanisky\.com wrote: :> Rafael Garcia-Suarez \rgarciasuarez@​free\.fr wrote: :> :Here's a cut-down version : :> : :> : my $x = 'x'; :> : print "${x}{"; :> : print "${x}["; :> : print "\n"; :> : :> :This simply prints '{['. :> : :> :Somehow the qq lexer doesn't see lexicals in this case. :> :> I think I looked at this a couple of years ago\, and got stuck. [...] :I applied patch 18687 from Enache Adrian that fixed this problem\, was :the patch incorrect?
Sorry\, I missed the patch\, and I suspect I must be remembering a different problem. The perils of running in catch-up mode. :(
Hugo
Enache Adrian wrote:
--- /arc/perl-current/toke.c 2003-02-10 21:23:38.000000000 +0200 +++ perl-current/toke.c 2003-02-13 03:31:00.000000000 +0200 @@ -6274\,8 +6274\,10 @@ S_scan_ident(pTHX_ register char *s\, reg } if (*s == '}') { s++; - if (PL_lex_state == LEX_INTERPNORMAL && !PL_lex_brackets) + if (PL_lex_state == LEX_INTERPNORMAL && !PL_lex_brackets) { PL_lex_state = LEX_INTERPEND; + PL_expect = XREF; + } if (funny == '#') funny = '@'; if (PL_lex_state == LEX_NORMAL) { @@ -6287\,8 +6289\,6 @@ S_scan_ident(pTHX_ register char *s\, reg funny\, dest\, funny\, dest); } } - if (PL_lex_inwhat == OP_STRINGIFY) - PL_expect = XREF; } else { s = bracket; /* let the parser handle it */
Thanks\, applied as #18753\, with some tests.
@rgs - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#20716 (status was 'resolved')
Searchable as RT20716$