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

strange behaviour (difference between perl 5.6 and perl 5.8.0) in the regexp #5960

Closed
p5pRT opened this issue Sep 26, 2002 · 6 comments
Closed

Comments

@p5pRT
Copy link

p5pRT commented Sep 26, 2002

Migrated from rt.perl.org#17605 (status was 'resolved')

Searchable as RT17605$

@p5pRT
Copy link
Author

p5pRT commented Sep 26, 2002

From infu@bastun.net

this script​:

$s = "something and another\n";
$s =~ s/something//e;
print $s;

Outputs in
  perl 5.6
  and another

  perl 5.8.0
  something and another
  and another

this difference somekind-a sucks but I guess it's not an error.

@p5pRT
Copy link
Author

p5pRT commented Oct 21, 2002

From @hvds

"Brain Sucker" (via RT) <perlbug@​perl.org> wrote​:
:this script​:
:
:$s = "something and another\n";
:$s =~ s/something//e;
:print $s;
:
:Outputs in
: perl 5.6
: and another
:
: perl 5.8.0
: something and another
: and another
:
:this difference somekind-a sucks but I guess it's not an error.

It turns out that executing the empty block results in the last
referenced expression getting grabbed off the stack, which in this
case is the string we're matching on. Things can go more badly
wrong if you do this more than twice​:
  crypt% perl -wle '$_ = "foo"; s/.//eg; print'
  Segmentation fault (core dumped)
  crypt%

I'm not sure what changed since 5.6 to cause that, but we used to
get back undef (as I would have expected). Andreas, could you
perhaps point your magic script at this to discover what patch
changed the behaviour?

Hugo

@p5pRT
Copy link
Author

p5pRT commented Oct 21, 2002

From @andk

On Mon, 21 Oct 2002 15​:34​:31 +0100, hv@​crypt.org (hv) said​:

  > crypt% perl -wle '$_ = "foo"; s/.//eg; print'
  > Segmentation fault (core dumped)
  > crypt%

  > I'm not sure what changed since 5.6 to cause that, but we used to
  > get back undef (as I would have expected). Andreas, could you
  > perhaps point your magic script at this to discover what patch
  > changed the behaviour?

Blame​: 11822

----Program----
#!/usr/bin/perl -wl
$_ = "foo"; s/.//eg; print

----Output of /usr/local/perl-5.7.2@​11821/bin/perl---
Use of uninitialized value in substitution iterator at tests/hv-regex-segv.pl line 2.
Use of uninitialized value in substitution iterator at tests/hv-regex-segv.pl line 2.
Use of uninitialized value in substitution iterator at tests/hv-regex-segv.pl line 2.

----EOF ($?='0')----
----Output of /usr/local/perl-5.7.2@​11822/bin/perl---

----EOF ($?='11')----

--
andreas

@p5pRT
Copy link
Author

p5pRT commented Nov 3, 2002

From @hvds

andreas.koenig@​anima.de (Andreas J. Koenig) wrote​:
:>>>>> On Mon, 21 Oct 2002 15​:34​:31 +0100, hv@​crypt.org (hv) said​:
:
: > crypt% perl -wle '$_ = "foo"; s/.//eg; print'
: > Segmentation fault (core dumped)
: > crypt%
:
: > I'm not sure what changed since 5.6 to cause that, but we used to
: > get back undef (as I would have expected). Andreas, could you
: > perhaps point your magic script at this to discover what patch
: > changed the behaviour?
:
:Blame​: 11822

Thanks muchly.

It turns out that patch, by replacing an empty block with a nextstate,
meant we no longer created an OP_STUB for such blocks. The patch below
(not yet applied) fixes that by adding the OP_STUB; perhaps we should
be looking to optimise away that stub when in list context.

It also changes the error message (again) for lvalue subroutines, so
that C< undef > (which now _is_ returned from an empty block in scalar
context) is trapped and separately diagnosed.

If no-one sees a disaster waiting to happen in this, I'll apply it in
a few days.

Hugo

Inline Patch
--- op.c.old	Tue Oct 22 19:14:24 2002
+++ op.c	Sun Nov  3 16:19:22 2002
@@ -1756,9 +1756,14 @@
 {
     int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
     line_t copline = PL_copline;
-    /* there should be a nextstate in every block */
-    OP* retval = seq ? scalarseq(seq) : newSTATEOP(0, Nullch, seq);
-    PL_copline = copline;  /* XXX newSTATEOP may reset PL_copline */
+    OP* retval = scalarseq(seq);
+    if (!seq) {
+	/* scalarseq() gave us an OP_STUB */
+	retval->op_flags |= OPf_PARENS;
+	/* there should be a nextstate in every block */
+	retval = newSTATEOP(0, Nullch, retval);
+	PL_copline = copline;  /* XXX newSTATEOP may reset PL_copline */
+    }
     LEAVE_SCOPE(floor);
     PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK);
     if (needblockscope)
--- pp_hot.c.old	Sat Oct 19 16:21:46 2002
+++ pp_hot.c	Sun Nov  3 16:11:28 2002
@@ -2317,8 +2317,9 @@
 		    PL_curpm = newpm;
 		    LEAVE;
 		    LEAVESUB(sv);
-		    DIE(aTHX_ "Can't return a %s from lvalue subroutine",
-			SvREADONLY(TOPs) ? "readonly value" : "temporary");
+		    DIE(aTHX_ "Can't return %s from lvalue subroutine",
+			SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef"
+			: "a readonly value" : "a temporary");
 		}
 		else {                  /* Can be a localized value
 					 * subject to deletion. */
--- t/op/sub_lval.t.old	Wed Apr 10 03:23:52 2002
+++ t/op/sub_lval.t	Sun Nov  3 16:20:19 2002
@@ -251,7 +251,7 @@
 EOE
 
 print "# '$_'.\nnot "
-  unless /Empty array returned from lvalue subroutine in scalar context/;
+  unless /Can't return undef from lvalue subroutine/;
 print "ok 31\n";
 
 sub lv10 : lvalue {}
@@ -274,7 +274,7 @@
 EOE
 
 print "# '$_'.\nnot "
-  unless /Can\'t return a readonly value from lvalue subroutine/;
+  unless /Can't return undef from lvalue subroutine/;
 print "ok 33\n";
 
 $_ = undef;
--- ext/B/B/Concise.pm.old	Sat Aug 17 03:04:42 2002
+++ ext/B/B/Concise.pm	Sun Nov  3 15:55:48 2002
@@ -533,7 +533,7 @@
 
 # Why these are different for MacOS?  Does it matter?
 my $cop_seq_mnum = $^O eq 'MacOS' ? 12 : 11;
-my $seq_mnum = $^O eq 'MacOS' ? 100 : 84;
+my $seq_mnum = $^O eq 'MacOS' ? 102 : 86;
 $cop_seq_base = svref_2object(eval 'sub{0;}')->START->cop_seq + $cop_seq_mnum;
 $seq_base = svref_2object(eval 'sub{}')->START->seq + $seq_mnum;
 
--- t/op/closure.t.old	Sun Nov  3 16:35:18 2002
+++ t/op/closure.t	Sun Nov  3 16:31:13 2002
@@ -13,7 +13,7 @@
 
 use Config;
 
-print "1..173\n";
+print "1..174\n";
 
 my $test = 1;
 sub test (&) {
@@ -527,3 +527,10 @@
 }->();
 test {1};
 
+# [perl #17605] found that an empty block called in scalar context
+# can lead to stack corruption
+{
+    my $x = "foooobar";
+    $x =~ s/o//eg;
+    test { $x eq 'fbar' }
+}

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2002

From @hvds

hv@​crypt.org wrote​:
:andreas.koenig@​anima.de (Andreas J. Koenig) wrote​:
:​:Blame​: 11822
:
:It turns out that patch, by replacing an empty block with a nextstate,
:meant we no longer created an OP_STUB for such blocks. The patch below
:(not yet applied) fixes that by adding the OP_STUB; perhaps we should
:be looking to optimise away that stub when in list context.
:
:It also changes the error message (again) for lvalue subroutines, so
:that C< undef > (which now _is_ returned from an empty block in scalar
:context) is trapped and separately diagnosed.

Now applied as #18118.

Hugo

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2002

@rspier - Status changed from 'new' to 'resolved'

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

1 participant