http://qs321.pair.com?node_id=558707

This was inspired by Re: Ideas Wanted for Perl::Critic Security Policies -- i decided to take a crack at making a Perl::Critic policy to
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)).

So here it is, in all it's glory .. I am a PPI novice, so comments/suggestions are very welcome. (Note: this was made by using ProhibitTwoArgOpen and ProhibitInterpolationOfLiterals as examples)
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;
(trivial) code to test against (note it doesn't catch the join one):
system("c:\\program\ files\\foo.exe"); system( join " ", qw/asd wqe/ ); system("wc /etc/hosts"); system("whoami"); exec("wc /etc/hosts"); exec("whoami");
Another problem case (or at least not covered by the above attempt) would be $cmd = "$prog $arg1 $arg2"; system($cmd);