Bug 183553

Summary: perlbug #38657: Using import() with arguments with -d: broke in 5.8.8, was okay in 5.8.7
Product: [Fedora] Fedora Reporter: Jason Vas Dias <jvdias>
Component: perlAssignee: Jason Vas Dias <jvdias>
Status: CLOSED RAWHIDE QA Contact: David Lawrence <dkl>
Severity: medium Docs Contact:
Priority: medium    
Version: rawhideCC: perl-devel, wtogami
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
URL: http://rt.perl.org/rt3/index.html?q=38657
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2006-03-01 23:47:22 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 185542    

Description Jason Vas Dias 2006-03-01 21:47:07 UTC
Description of problem:

Copied from perlbug #38657: http://rt.perl.org/rt3/index.html?q=38657 :

Using import() with arguments with -d: broke in 5.8.8, was okay in 5.8.7.

$ mkdir -p lib/Devel
$ echo 'package Devel::Foo; sub import { print "import(@_)" } sub
\ DB::DB { } 1' > lib/Devel/Foo.pm
$ /tmp/jhi/p587/bin/perl -wIlib -d:Foo -le 1
import(Devel::Foo)
$ /tmp/jhi/p588/bin/perl -wIlib -d:Foo -le 1
import(Devel::Foo)
$ /tmp/jhi/p587/bin/perl -wIlib -d:Foo=bar -le 1
import(Devel::Foo bar)
$ /tmp/jhi/p588/bin/perl -wIlib -d:Foo=bar -le 1
Can't find string terminator ";" anywhere before EOF.
$ 


Version-Release number of selected component (if applicable):
perl-5.8.8

How reproducible:
100%

Steps to Reproduce:
See above

Comment 1 Jason Vas Dias 2006-03-01 21:53:41 UTC
I have reproduced this problem, and confirmed the code above used to work on
perl-5.8.6 . Suggested fix:
---
From: "Rafael Garcia-Suarez" <rgarciasuarez>
  To: perl5-porters
Date: 2006-03-01 16:16

On 3/1/06, via RT jhi @ ugli. hut. fi <perlbug-followup> wrote:
> $ /tmp/jhi/p587/bin/perl -wIlib -d:Foo=bar -le 1
> import(Devel::Foo bar)
> $ /tmp/jhi/p588/bin/perl -wIlib -d:Foo=bar -le 1
> Can't find string terminator ";" anywhere before EOF.

Bad news, guys. This patch solves it :

==== //depot/perl/perl.c#736 - /home/rafael/p4blead/perl.c ====
--- /home/rafael/tmp/tmp.9616.0 2006-03-01 22:18:07.000000000 +0100
+++ /home/rafael/p4blead/perl.c 2006-03-01 22:18:04.000000000 +0100
@@ -3031,7 +3031,7 @@ Perl_moreswitches(pTHX_ char *s)
                sv_catpv(sv, start);
            else {
                sv_catpvn(sv, start, s-start);
-               Perl_sv_catpvf(aTHX_ sv, " split(/,/,q%c%s%c)", 0, ++s, 0);
+               Perl_sv_catpvf(aTHX_ sv, " split(/,/,q(%s))", ++s);
            }
            s += strlen(s);
            my_setenv("PERL5DB", SvPV_nolen_const(sv));

That means that using \0 as a q() delimiter no longer works.
---

Now testing this.

Comment 2 Jason Vas Dias 2006-03-01 22:08:02 UTC
Actually, the above fix was for bleadperl; I think it's probably better to revert
to 5.8.7's code for the above, which was:
---
            /* We now allow -d:Module=Foo,Bar */
            while(isALNUM(*s) || *s==':') ++s;
            if (*s != '=')
                sv_catpv(sv, start);
            else {
                sv_catpvn(sv, start, s-start);
                sv_catpv(sv, " split(/,/,q{");
                sv_catpv(sv, ++s);
                sv_catpv(sv, "})");
            }
---


Comment 3 Rafael Garcia-Suarez 2006-03-01 22:11:54 UTC
Hold on guys, the patch I posted on P5P is just here to demonstrate the cause of
the problem, not to be applied. q\0foo\0 ought to be equivalent to 'foo'. It was
working in previous perls. Still looking for a proper fix (sorry for haven't
been clear enough)

Comment 4 Jason Vas Dias 2006-03-01 22:21:59 UTC
Yes, I noticed that - I'm not applying anything yet - I'm also still investigating
- many thanks, Rafael


Comment 5 Jason Vas Dias 2006-03-01 23:07:58 UTC
Actually, under perl-5.8.0, perl-5.8.5, perl-5.8.6, and perl-5.8.7, 
'q\0foo\0' does NOT work (I have tested all versions) - I get the
same result :

$ perl -e '$s=q\0foo\0;'
Number found where operator expected at -e line 1, near "q\0foo\0"
syntax error at -e line 1, near "q\0foo\0"
Execution of -e aborted due to compilation errors.

This is because '\' is a legal delimiter for q(), and the parse breaks
on the last '0;' .

$ perl -e '$s=q\0foo\; print $s,"\n";'
0foo

But if I actually create a file with 'q{0x0}foo{0x0}', it DOES work OK on all 
versions:

$ cat tq.pl
#!/usr/bin/perl
$s=q0foo0;
print "$s\n";
$ ./tq.pl
q0foo0
$ tr '0' '\0' < tq.pl > tq0.pl
$ od -c tq0.pl
0000000   #   !   /   u   s   r   /   b   i   n   /   p   e   r   l  \n
0000020   $   s   =   q  \0   f   o   o  \0   ;  \n   p   r   i   n   t
0000040       "   $   s   \   n   "   ;  \n
0000051
$ ./tq0.pl
foo

So q\0foo\0 with real, unescaped 0x0 chars DOES work OK on all versions .

I think it is just that 0x0 is a bad choice for a '%c' in Perl_sv_catpvf, as
it terminates the C string, and the interpreter doesn't get the rest of the
expression . So I think the first fix posted is OK .

If we really must make Perl_sv_catpvf handle 0x0 chars OK in expressions, 
that is a different problem - I think it is debatable whether it is a problem
worth fixing.

Comment 6 Rafael Garcia-Suarez 2006-03-01 23:14:03 UTC
Actually it works, yes, but due to shell quoting, you need to be clever :

$ perl -le 'print eval "q\0foo\0"'
foo

and that was what I meant.
The problem was with the setenv, a bit later, because setenv expects
\0-terminated strings. Fixed upstream now. Looks like my first patch was correct
after all :)

Comment 7 Jason Vas Dias 2006-03-01 23:47:22 UTC
fixed with perl-5.8.8-4, now in rawhide

Comment 8 Warren Togami 2006-03-02 03:22:18 UTC
No, now it is in rawhide (moving now).  I'm guessing that Jason has been very
careful about testing this change like many previous changes that I've seen him
do.  Great work Jason.