warn about system or exec calls that pass arguments inside the first parameter (i.e. system("$command $arg1 $arg2") instead of system($command, $arg1, $arg2)).
(trivial) code to test against (note it doesn't catch the join one):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;
Another problem case (or at least not covered by the above attempt) would be $cmd = "$prog $arg1 $arg2"; system($cmd);system("c:\\program\ files\\foo.exe"); system( join " ", qw/asd wqe/ ); system("wc /etc/hosts"); system("whoami"); exec("wc /etc/hosts"); exec("whoami");
In reply to RFC: Perl-Critic policy: ProhibitInlineSystemArgs by davidrw
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |