Ved bruk av system () kaller i Perl, har du å flykte skallet args, eller er det gjort automatisk?
Argumentene vil være brukerundersøkelser, så jeg ønsker å sørge for at dette ikke utnyttes.
Ved bruk av system () kaller i Perl, har du å flykte skallet args, eller er det gjort automatisk?
Argumentene vil være brukerundersøkelser, så jeg ønsker å sørge for at dette ikke utnyttes.
Hvis du bruker system $cmd, @args
i stedet for system "$cmd @args"
(en matrise i stedet for en streng), så du trenger ikke å unnslippe argumentene fordi ingen skallet er påberopt (se system ). system {$cmd} $cmd, @args
vil ikke påkalle en skall enten selv om $ cmd inneholder metategn og @args er tom (dette er dokumentert som en del av exec ). Hvis args kommer fra brukerundersøkelser (eller annen upålitelig kilde), vil du fortsatt ønsker å untaint dem. Se -T
på perlrun docs, og perlsec docs.
Hvis du trenger å lese utgang eller sende innspill til kommandoen, qx
og readpipe
har ikke noe tilsvarende. I stedet bruker open my $output, "-|", $cmd, @args
eller open my $input, "|-", $cmd, @args
selv om dette ikke er bærbar som det krever en reell fork
som betyr Unix bare ... tror jeg. Kanskje det vil fungere på Windows med simulert gaffel. Et bedre alternativ er noe som IPC :: Run , som også vil håndtere saken av rør kommandoer til andre kommandoer, som verken multi-arg form for system eller 4 arg form for åpen vil håndtere.
På Windows, er situasjonen en litt slemmere. I utgangspunktet alle Win32 programmer får en lang kommando-linje streng - skallet (vanligvis cmd.exe
) kan gjøre noen tolkning første, fjerne <
og >
redirections for eksempel, men det trenger ikke dele den opp på ordet grenser for programmet. Hvert program må gjøre dette parsing seg selv (hvis de ønsker det - noen programmer ikke bry). I C og C ++ programmer, vil rutiner gitt av kjøretidsbiblioteker som følger med kompilatoren-verktøyene generelt utføre denne parsing trinnet før main()
kalles.
Problemet er, generelt, trenger du ikke vet hvordan et gitt program vil analysere sin kommandolinjen . Mange programmer er kompilert med en versjon av MSVC ++, hvis quirky parsing Reglene er beskrevet her , men mange andre er kompilert med ulike kompilatorer som bruker ulike konvensjoner.
Dette er forsterket av det faktum at cmd.exe
har sine egne sære parsing regler. Cirkumflekstegnet ( ^
) behandles som en flukt karakter som siterer følgende karakter, og teksten i anførselstegn behandles som sitert om en liste over vanskelige kriterier er oppfylt (se cmd /?
for full blodig detaljer). Hvis din kommando inneholder noen rare tegn, er det veldig lett for cmd.exe
sin idé om hvilke deler av teksten er 'sitert' og som ikke er til å komme ut av sync med målet for programmet, og helvete bryter løs.
Så, den sikreste metode for å unnslippe argumenter på Windows er:
^
.&&
).system()
eller backticks.Svarene på spørsmålet ditt var svært nyttig. Til slutt fulgte jeg @ Runrig råd, men da anvendes kjernemodulen open3 () -kommando slik at jeg kan fange opp utgangssignalet fra STDERR samt STDOUT.
For eksempelkode for open3 () i bruk med @ Runrig løsning, se min relaterte spørsmål og svar:
Calling system kommandoer fra Perl
sub esc_chars {
# will change, for example, a!!a to a\!\!a
@_ =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
return @_;
}
http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html
Hvis du bruker system "$ cmd @args" (en streng), så må du unnslippe argumentene fordi en skallet er påberopt.
Heldigvis for dobbel sitert strenger, bare fire tegn må rømme:
" - double quote
$ - dollar
@ - at symbol
\ - backslash