perlmeditation
davidrw
This was inspired by [id://558656] -- i decided to take a crack at making a [module://Perl::Critic] policy to
<blockquote><i>warn about system or exec calls that pass arguments inside the first parameter (i.e. <c>system("$command $arg1 $arg2")</c> instead of <c>system($command, $arg1, $arg2)</c>).</i></blockquote><br>
So here it is, in all it's glory .. I am a [module://PPI] novice, so comments/suggestions are very welcome. (Note: this was made by using [module://Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen|ProhibitTwoArgOpen] and [module://Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals|ProhibitInterpolationOfLiterals] as examples)
<code>
package Perl::Critic::Policy::DRW::ProhibitInlineSystemArgs;
use strict;
use warnings;
use Perl::Critic::Utils;
use Perl::Critic::Violation;
use base 'Perl::Critic::Policy';
our $VERSION = '0.01';
$VERSION = eval $VERSION; ## no critic
#--------------------------------------------------------------------------
my $desc = q{Inline-args in 'system' or 'exec' used};
my $expl = [];
#--------------------------------------------------------------------------
sub default_severity { return $SEVERITY_HIGHEST }
sub applies_to { return 'PPI::Token::Word' }
#--------------------------------------------------------------------------
sub violates {
my ($self, $elem, $doc) = @_;
return if !($elem eq 'system' || $elem eq 'exec');
return if is_method_call($elem);
return if is_hash_key($elem);
my @args = parse_arg_list($elem);
return unless @args && @{$args[0]};
my $firstArg = $args[0]->[0];
return unless defined $firstArg && (
$firstArg->isa('PPI::Token::Quote::Double')
|| $firstArg->isa('PPI::Token::Quote::Interpolate')
);
if( $firstArg =~ m{ (?<!\\) [\ ] \S+ }mx ){ # has unescaped space
my $sev = $self->get_severity();
return Perl::Critic::Violation->new( $desc, $expl, $elem, $sev );
}
return; #ok!
}
1;
</code>
(trivial) code to test against (note it doesn't catch the <c>join</c> one):
<code>
system("c:\\program\ files\\foo.exe");
system( join " ", qw/asd wqe/ );
system("wc /etc/hosts");
system("whoami");
exec("wc /etc/hosts");
exec("whoami");
</code>
Another problem case (or at least not covered by the above attempt) would be <c>$cmd = "$prog $arg1 $arg2"; system($cmd);</c>