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

[PATCH] "#!perl -i whatever" is interpreted as "#!perl -i -whatever" #15623

Closed
p5pRT opened this issue Sep 23, 2016 · 9 comments
Closed

[PATCH] "#!perl -i whatever" is interpreted as "#!perl -i -whatever" #15623

p5pRT opened this issue Sep 23, 2016 · 9 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 23, 2016

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

Searchable as RT129336$

@p5pRT
Copy link
Author

p5pRT commented Sep 23, 2016

From @dcollinsn

Hello,

There is a bug in argument parsing of the -i flag. Perl_moreswitches processes a single switch, and returns a pointer to the start of the next switch. It can return either the a pointer to the next flag itself​:

  #!perl -n -p
  ^ Can point here

Or, to the space before the next "arg"​:

  #!perl -n -p
  ^ Can point here

(Where the next call to Perl_moreswitches will consume " -".)

In the case of -i[extension], the pointer is by default pointing at the space after the end of the argument. The current code tries to do the former, by unconditionally advancing the pointer, and then advancing it again if it is on a '-'. But that is incorrect​:

  #!perl -i p
  ^ Will point here, but that isn't a flag

This is a problem if -i is the last argument before either a file name, or a malformed argument. This normally isn't a problem on the command line because Perl_moreswitches operates on elements of `argv` one at a time. However, someone who typed `perl "-ifoo Vbar.pl"` into bash, or someone who has a messed up #! line, will encounter this.

I could fix this by removing the unconditional s++, and having it increment by 2 if *(s+1)=='-', but this work isn't actually necessary - it's better to just remove the special-casing for -i and leave it pointing at the space after the argument.

Found with AFL, believe it or not. This is not a regression, and all tests pass for me. I've added a test for this, it basically makes sure that `#!perl -i u` does /not/ crash.

Clicking submit so I get an RT number.

--
Respectfully,
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Sep 23, 2016

From @dcollinsn

On Thu Sep 22 23​:22​:45 2016, dcollinsn@​gmail.com wrote​:

Hello,

There is a bug in argument parsing of the -i flag. Perl_moreswitches
processes a single switch, and returns a pointer to the start of the
next switch. It can return either the a pointer to the next flag
itself​:

#!perl -n -p
^ Can point here

Or, to the space before the next "arg"​:

#!perl -n -p
^ Can point here

(Where the next call to Perl_moreswitches will consume " -".)

In the case of -i[extension], the pointer is by default pointing at
the space after the end of the argument. The current code tries to do
the former, by unconditionally advancing the pointer, and then
advancing it again if it is on a '-'. But that is incorrect​:

#!perl -i p
^ Will point here, but that isn't a flag

This is a problem if -i is the last argument before either a file
name, or a malformed argument. This normally isn't a problem on the
command line because Perl_moreswitches operates on elements of `argv`
one at a time. However, someone who typed `perl "-ifoo Vbar.pl"` into
bash, or someone who has a messed up #! line, will encounter this.

I could fix this by removing the unconditional s++, and having it
increment by 2 if *(s+1)=='-', but this work isn't actually necessary
- it's better to just remove the special-casing for -i and leave it
pointing at the space after the argument.

Found with AFL, believe it or not. This is not a regression, and all
tests pass for me. I've added a test for this, it basically makes sure
that `#!perl -i u` does /not/ crash.

Clicking submit so I get an RT number.

Patch attached.

--
Respectfully,
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Sep 23, 2016

From @dcollinsn

0001-rt-129336-perl-i-u-erroneously-interpreted-as-u.patch
From 757b1c7109f3e69d2717b5187e58e78537dd5101 Mon Sep 17 00:00:00 2001
From: Dan Collins <dcollinsn@gmail.com>
Date: Fri, 23 Sep 2016 01:21:20 -0400
Subject: [PATCH] [rt #129336] #!perl -i u erroneously interpreted as -u

Perl_moreswitches processes a single switch, and returns a pointer
to the start of the next switch. It can return either
the a pointer to the next flag itself:

    #!perl -n -p
               ^ Can point here

Or, to the space before the next "arg":

    #!perl -n -p
             ^ Can point here

(Where the next call to Perl_moreswitches will consume " -".)

In the case of -i[extension], the pointer is by default pointing at
the space after the end of the argument. The current code tries to
do the former, by unconditionally advancing the pointer, and then
advancing it again if it is on a '-'. But that is incorrect:

    #!perl -i p
              ^ Will point here, but that isn't a flag

I could fix this by removing the unconditional s++, and having it
increment by 2 if *(s+1)=='-', but this work isn't actually
necessary - it's better to just leave it pointing at the space after
the argument.
---
 perl.c     | 5 -----
 t/op/lex.t | 9 ++++++++-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/perl.c b/perl.c
index 07b8523..ba6d5af 100644
--- a/perl.c
+++ b/perl.c
@@ -3349,11 +3349,6 @@ Perl_moreswitches(pTHX_ const char *s)
 
 	    PL_inplace = savepvn(start, s - start);
 	}
-	if (*s) {
-	    ++s;
-	    if (*s == '-')	/* Additional switches on #! line. */
-		s++;
-	}
 	return s;
     case 'I':	/* -I handled both here and in parse_body() */
 	forbid_setid('I', FALSE);
diff --git a/t/op/lex.t b/t/op/lex.t
index a667183..9696669 100644
--- a/t/op/lex.t
+++ b/t/op/lex.t
@@ -7,7 +7,7 @@ use warnings;
 
 BEGIN { chdir 't' if -d 't'; require './test.pl'; }
 
-plan(tests => 30);
+plan(tests => 31);
 
 {
     no warnings 'deprecated';
@@ -241,3 +241,10 @@ fresh_perl_is(
     {},
     '[perl #129069] - "Missing name" warning and valgrind clean'
 );
+
+fresh_perl_like(
+    "#!perl -i u\nprint 'OK'",
+    qr/OK/,
+    {},
+    '[perl #129336] - #!perl -i argument handling'
+);
-- 
2.9.3

@p5pRT
Copy link
Author

p5pRT commented Sep 23, 2016

From [Unknown Contact. See original ticket]

On Thu Sep 22 23​:22​:45 2016, dcollinsn@​gmail.com wrote​:

Hello,

There is a bug in argument parsing of the -i flag. Perl_moreswitches
processes a single switch, and returns a pointer to the start of the
next switch. It can return either the a pointer to the next flag
itself​:

#!perl -n -p
^ Can point here

Or, to the space before the next "arg"​:

#!perl -n -p
^ Can point here

(Where the next call to Perl_moreswitches will consume " -".)

In the case of -i[extension], the pointer is by default pointing at
the space after the end of the argument. The current code tries to do
the former, by unconditionally advancing the pointer, and then
advancing it again if it is on a '-'. But that is incorrect​:

#!perl -i p
^ Will point here, but that isn't a flag

This is a problem if -i is the last argument before either a file
name, or a malformed argument. This normally isn't a problem on the
command line because Perl_moreswitches operates on elements of `argv`
one at a time. However, someone who typed `perl "-ifoo Vbar.pl"` into
bash, or someone who has a messed up #! line, will encounter this.

I could fix this by removing the unconditional s++, and having it
increment by 2 if *(s+1)=='-', but this work isn't actually necessary
- it's better to just remove the special-casing for -i and leave it
pointing at the space after the argument.

Found with AFL, believe it or not. This is not a regression, and all
tests pass for me. I've added a test for this, it basically makes sure
that `#!perl -i u` does /not/ crash.

Clicking submit so I get an RT number.

Patch attached.

--
Respectfully,
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2016

From @tonycoz

On Thu Sep 22 23​:25​:11 2016, dcollinsn@​gmail.com wrote​:

Patch attached.

Thanks, applied as f54cfda.

Tony

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 11, 2016

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release today of Perl 5.26.0, this and 210 other issues have been
resolved.

Perl 5.26.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.26.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

@khwilliamson - Status changed from 'pending release' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant