Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Sep 1998 18:25:43 -0700 (PDT)
From:      bmah@ca.sandia.gov
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   ports/8053: Perl 5 port has broken foreach behavior, possible fix
Message-ID:  <199809260125.SAA10576@eisenhower.ca.sandia.gov>

next in thread | raw e-mail | index | archive | help

>Number:         8053
>Category:       ports
>Synopsis:       Perl 5 port has broken foreach behavior, possible fix
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-ports
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 25 18:30:00 PDT 1998
>Last-Modified:
>Originator:     Bruce A. Mah
>Organization:
Sandia National Laboratories
>Release:        FreeBSD 2.2.7-RELEASE i386
>Environment:

2.2.7-RELEASE, perl5 port cvsup'ed and compiled 23 September 1998

>Description:

Perl code that relies on the index variable in a foreach command may
get the wrong answer.  This breaks vnc, and very likely other things
as well.

>How-To-Repeat:

Run the following perl script, which is an excerpt from vncserver(1):

-----8< snip 8<-----
#!/usr/local/bin/perl

$displayNumber = &GetDisplayNumber();
print "use display $displayNumber\n";
exit;

sub GetDisplayNumber
{
    foreach $n (1..99) {
        return $n;
    }
}
-----8< snip 8<-----

The expected output is "use display 1".  Our perl prints "use display ".

>Fix:

The following was forwarded from Jeff Mark <J.Mark@iname.com>, 
via the vnc-list mailing list.  Extremely cursory testing shows that it
seems to fix the problem.

From: "Gurusamy Sarathy" <gsar@engin.umich.edu>
To: <fmc@mugwump-prv.incyte.com>
Cc: <perlbug@perl.com>,
	<hansm@icgroup.nl>,
	"Jeff Mark" <J.Mark@dialogic.com>
Subject: Re: lexical gets freed too soon ? 
Date: Fri, 18 Sep 1998 11:18:19 -0700
Message-ID: <199809181818.OAA09898@aatma.engin.umich.edu>
MIME-Version: 1.0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook 8.5, Build 4.71.2232.26
X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2106.4
Importance: Normal
In-Reply-To: Your message of "Thu, 17 Sep 1998 17:00:37 PDT."            <199809180000.RAA21930@mugwump-prv.incyte.com> 

On Thu, 17 Sep 1998 17:00:37 PDT, Frederic Chauveau wrote:
>Audit-Trail:
>Unformatted:
>The following snippet of code used to work in 5.003, is broken in
>both 5.005 and 5.005_51...
>
>It 'looks' like the temporary index for foreach gets free'd a bit too
soon...
>
>Is there's a patch (or something in the doc :) ?

Thanks to all the people that have reported the problem.  Here's a patch.

I think a possibly more complicated fix is also possible if we fix
pp_return() to split the POPLOOP() like pp_leaveloop() and the others,
but I'll look into that later.

 - Sarathy.
   gsar@engin.umich.edu
-----------------------------------8<-----------------------------------
Change 1789 by gsar@aatma on 1998/09/18 18:01:37

	delay freeing itervar so C<for $i (@a) { return($i) }> works

Affected files ...

... //depot/perl/cop.h#14 edit
... //depot/perl/t/cmd/for.t#6 edit

Differences ...

==== //depot/perl/cop.h#14 (text) ====
Index: perl/cop.h
--- perl/cop.h.~1~	Fri Sep 18 14:13:08 1998
+++ perl/cop.h	Fri Sep 18 14:13:08 1998
@@ -143,7 +143,7 @@
 #define POPLOOP2()							\
 	SvREFCNT_dec(cxloop.iterlval);					\
 	if (cxloop.itervar) {						\
-	    SvREFCNT_dec(*cxloop.itervar);				\
+	    sv_2mortal(*cxloop.itervar);				\
 	    *cxloop.itervar = cxloop.itersave;				\
 	}								\
 	if (cxloop.iterary && cxloop.iterary != PL_curstack)		\

==== //depot/perl/t/cmd/for.t#6 (xtext) ====
Index: perl/t/cmd/for.t
--- perl/t/cmd/for.t.~1~	Fri Sep 18 14:13:08 1998
+++ perl/t/cmd/for.t	Fri Sep 18 14:13:08 1998
@@ -1,9 +1,7 @@
 #!./perl

-# $RCSfile: for.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:09 $
-
-print "1..7\n";
+print "1..10\n";

 for ($i = 0; $i <= 10; $i++) {
     $x[$i] = $i;
 }
@@ -46,4 +44,14 @@

 foreach $foo (("ok 6\n","ok 7\n")) {
 	print $foo;
+}
+
+sub foo {
+    for $i (1..5) {
+	return $i if $_[0] == $i;
+    }
 }
+
+print foo(1) == 1 ? "ok" : "not ok", " 8\n";
+print foo(2) == 2 ? "ok" : "not ok", " 9\n";
+print foo(5) == 5 ? "ok" : "not ok", " 10\n";
End of Patch.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809260125.SAA10576>