셸 스크립팅 · 입력과 인자를 안전하게 다루기 · 실습
적대적인 이름을 견디는 스크립트
목표
공백·줄바꿈·대시로 시작하는 파일 이름과, 옵션과 주입 문자열까지 견디는
스크립트를 씁니다. 각 규칙을 깨진 쪽과 고친 쪽을 나란히 두고 확인합니다.
환경
/root/args 아래에서 작업합니다. 재료는 직접 만듭니다.
mkdir -p /root/args/data && cd /root/args/data: > "my report.tmp": > "$(printf 'twolines').txt": > "-rf": > "normal.txt"ls -b세 번째가 핵심입니다. -rf 라는 이름의 파일을 만들 수 있습니다. 그리고
두 번째처럼 이름에 줄바꿈도 들어갑니다 — 파일명에 못 들어가는 문자는
NUL 하나뿐입니다.
만들 것
/root/args/split.txt 따옴표 유무에 따른 인자 수/root/args/nul.txt 줄 단위와 NUL 단위로 센 개수/root/args/clean.sh 파일 하나를 이름이 무엇이든 안전하게 지운다/root/args/wrap.sh 받은 인자를 쪼개지 않고 그대로 넘긴다/root/args/opts.sh getopts 로 옵션을 판다/root/args/search.sh 입력을 값으로만 쓴다/root/args/report.md 다섯 규칙 정리채점 방식
3~7단계는 채점기가 여러분의 스크립트를 적대적인 입력으로 직접 호출합니다.
wrap.sh "a b" "c" "d e" 를 넘겨 3개로 도착하는지opts.sh -v -o 값 / 붙여 쓴 -vo 값 / 값 빠진 -o / 모르는 -Zsearch.sh "alpha; touch /tmp/…" 를 넣고 그 파일이 생기는지clean.sh "-rf" 라는 이름을 인자로 직접 넘겨 지워지는지단계
1. 적대적인 이름 네 종류를 만듭니다.
2. 같은 값에 따옴표를 붙였을 때와 뺐을 때의 인자 수를 세어 적습니다.
3. 같은 디렉터리를 줄 단위로 셀 때와 -print0 으로 셀 때의 개수를 적습니다.
두 숫자가 다릅니다.
4. clean.sh 를 씁니다. 파일 이름 하나를 인자로 받아 지웁니다. 없는 파일이면
0 이 아닌 코드로 끝나야 합니다.
5. wrap.sh 를 씁니다. 받은 인자마다 ARG:<값> 을 한 줄씩 냅니다.
6. opts.sh 를 씁니다. -v, -o <값> 을 받고 나머지 인자 수를 냅니다.
출력은 verbose=0 out= rest=0 형태입니다.
7. search.sh 를 씁니다. 패턴과 파일을 받아 검색합니다. eval 은 쓰지 않습니다.
8. 다섯 규칙과 그 근거를 정리합니다.
참고
4단계에서 find 로 이름을 뽑으면 앞에 ./ 가 붙어 문제가 가려집니다.
그래서 채점기는 이름을 인자로 직접 넘깁니다. 현장에서도 그 형태가 위험합니다 —for f in * 나 다른 프로그램이 준 이름을 그대로 넘길 때입니다.
단계 8개
- 적대적인 이름 만들기
- 따옴표 하나로 인자 수가 바뀐다
- 줄로 세면 틀리고 NUL 로 세면 맞다
- 이름이 대시로 시작할 때
- 받은 인자를 그대로 넘기기
- 옵션 파서는 직접 만들지 않는다
- 입력은 값이지 코드가 아니다
- 다섯 규칙 정리