답변:
첫째, 많은 유틸리티와 마찬가지로 파일 이름으로 시작하는 문제가 있습니다 -
. 있는 동안 :
sh -c 'inline sh script here' other args
다른 인수는 inline sh script
; 와 perl
동등한
perl -e 'inline perl script here' other args
다른 인수는 인라인 스크립트가 아닌 펄을 우선으로 하는 추가 옵션이 있는지 검사합니다 . 예를 들어 -eBEGIN{do something evil}
현재 디렉토리에 파일이 있으면
perl -ne 'inline perl script here;' *
(의 유무에 관계없이 -n
) 악한 일을합니다.
다른 유틸리티와 마찬가지로 해결 방법은 옵션 끝 마커 ( --
)를 사용하는 것입니다.
perl -ne 'inline perl script here;' -- *
그러나 그럼에도 불구하고 여전히 위험하며 /에 <>
의해 사용되는 운영자 에게 달려 있습니다.-n
-p
문제는 perldoc perlop
설명서에 설명되어 있습니다.
이 특수 연산자는 입력의 한 줄 (하나의 레코드, 기본적으로 레코드 인 줄)을 읽는 데 사용됩니다. 여기서 해당 입력은에서 전달 된 각 인수에서옵니다 @ARGV
.
에서:
perl -pe '' a b
-p
while (<>)
코드 주위 에 루프가 있음을 나타냅니다 (여기서는 비어 있음).
<>
먼저 열리고 a
파일이 소진 될 때까지 한 번에 한 줄씩 레코드를 읽은 다음 열 것입니다 b
...
문제는 파일을 열 때 안전하지 않은 첫 번째 형식을 사용한다는 것입니다 open
.
open ARGV, "the file as provided"
그 형식으로 논쟁이
"> afile"
afile
쓰기 모드에서 열립니다 ."cmd|"
을 실행 cmd
하고 출력을 읽습니다."|cmd"
의 입력에 쓸 수있는 스트림이 열려 cmd
있습니다.예를 들어 :
perl -pe '' 'uname|'
호출 된 파일의 내용 uname|
(완전히 유효한 파일 이름 btw)은 출력하지 않지만 uname
명령 의 출력은 출력하지 않습니다 .
당신이 실행중인 경우 :
perl -ne 'something' -- *
그리고 누군가가 rm -rf "$HOME"|
현재 디렉토리에 (완전히 유효한 파일 이름) 이라는 파일을 만들었습니다 (예를 들어, 다른 사람이 해당 디렉토리를 한 번 쓸 수 있었거나, dodgy 아카이브를 추출했거나 dodgy 명령을 실행했거나, 다른 소프트웨어의 또 다른 취약점이 악용되었습니다)) 그러면 큰 어려움에 처하게됩니다. 이 문제를 인식하는 것이 중요한 영역 은 공용 영역 /tmp
(또는 이러한 도구에서 호출 할 수있는 도구)과 같은 공용 영역 에서 자동으로 파일을 처리하는 도구입니다.
라는 파일은 > foo
, foo|
, |foo
문제가 있습니다. 그러나 조금 적게 < foo
하고 foo
잘하는 수단으로 그 파일이 처리되지 않거나 잘못된 될 것으로 (공백, 탭, 줄 바꿈, 이러다 ... 포함) 선행 또는 후행 ASCII 간격 문자.
또한 멀티 바이트 문자 세트 ( ǖ
BIG5-HKSCS 와 같은)의 일부 문자는 0x7c의 바이트 인코딩으로 끝나는 점에 유의하십시오 |
.
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
따라서 해당 문자셋을 사용하는 로케일에서
perl -pe '' ./nǖ
실행하려고시겠습니까 ./n\x88
로 명령을 perl
할 수 없습니다 사용자의 로케일에서 해당 파일 이름을 해석하려고!
AFAIK, perl
시스템 전체에서 안전하지 않은 기본 동작을 한 번만 변경하려면 수행 할 수있는 작업이 없습니다 .
첫째, 파일 이름의 시작과 끝에있는 문자에서만 문제가 발생합니다. 따라서 문제가 perl -ne '' *
있거나perl -ne '' *.txt
perl -ne 'some code' ./*.txt
모든 인수는 이제 시작되지 않기 때문에 ./
그리고 결국 .txt
(그렇게하지 -
, <
, >
, |
..., 공간). 더 일반적으로, 그것은 좋은 아이디어에 접두사의 globs와 와 함께 ./
. 또한 다른 많은 유틸리티로 -
시작하거나 파일에서 시작하는 문제를 피할 수 -
있습니다 (여기서 옵션 끝 ( --
) 표시자가 더 이상 필요하지 않음 ).
사용 -T
켭 taint
모드 것은 어느 정도 도움이됩니다. 이러한 악의적 인 파일이 발견되면 명령이 중단됩니다 ( >
및 공백이 |
아닌 및 경우 에만 해당 <
).
이러한 명령을 대화식으로 사용할 때 유용한 정보가 있다는 것을 알려주므로 유용합니다. 자동 처리를 수행 할 때는 바람직하지 않을 수 있습니다. 즉, 누군가 파일을 작성하여 처리를 실패 하게 할 수 있기 때문 입니다.
이름에 관계없이 모든 파일을 처리 하려면 CPAN 에서 ARGV::readonly
perl
모듈을 사용할 수 있습니다 (불행하게도 기본적으로 설치되지 않음). 그것은 매우 짧은 모듈입니다.
sub import{ # Tom Christiansen in Message-ID: <24692.1217339882@chthon> # reccomends essentially the following: for (@ARGV){ s/^(\s+)/.\/$1/; # leading whitespace preserved s/^/< /; # force open for input $_.=qq/\0/; # trailing whitespace preserved & pipes forbidden }; };
기본적으로 " foo|"
예를 들어로 전환 하여 @ARGV를 소독 "< ./ foo|\0"
합니다.
명령 의 BEGIN
명령문에서 동일한 작업을 수행 할 수 있습니다 perl -n/-p
.
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
여기서는 ./
사용중인 가정을 단순화합니다 .
ARGV::readonly
그러나 (및 ) 의 부작용 은 그 뒤에 나오는 NUL 문자 $ARGV
를 your code here
보여줍니다.
perl
v5.21.5 이상에는 특수 처리를 수행하지 않는 것을 제외하고는 <<>>
작동 하는 새 연산자가 있습니다. 인수는 파일 이름으로 만 간주됩니다. 따라서 해당 버전으로 다음과 같이 작성할 수 있습니다.<>
perl -e 'while(<<>>){ ...;}' -- *
합니다 (잊지 마세요 --
또는 사용 ./*
이 파일을 덮어 쓰거나 예기치 않은 명령을 실행 두려움없이 생각을).
-n
/ -p
그래도 위험한 <>
형태를 사용하십시오 . 그리고 심볼릭 링크를 계속 따르고 있으므로 반드시 신뢰할 수없는 디렉토리에서 사용하는 것이 안전하지는 않습니다.
@ Stéphane Chazelas의 답변 외에도 -i
명령 줄 옵션을 사용하면이 문제에 대해 걱정할 필요가 없습니다 .
$ perl -pe '' 'uname|'
Linux
$ perl -i -pe '' 'uname|'
Can't open uname|: No such file or directory.
-i
옵션을 perl
사용할 때 파일을 처리하기 전에 stat 를 사용 하여 파일 상태를 확인하십시오.
$ strace -fe trace=stat perl -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
Process 6106 attached
Linux
Process 6105 suspended
Process 6105 resumed
Process 6106 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
$ strace -fe trace=stat perl -i -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("uname|", 0x785f40) = -1 ENOENT (No such file or directory)
Can't open uname|: No such file or directory.
stat
수표와 유효한 펄 처리 사이에 경쟁 조건이있을 수 있습니까?
stat
. 파일 을 제자리에서 -i
편집 하는 것 뿐 이므로 실제 파일 경로 이외의 인수를 허용하는 것은 합리적이지 않으므로 특수 처리가 수행되지 않습니다. -i