LabHub

셸 스크립팅 · 입력과 인자를 안전하게 다루기 · 실습

적대적인 이름을 견디는 스크립트

LabHub 에서 이어서 보기

목표

공백·줄바꿈·대시로 시작하는 파일 이름과, 옵션과 주입 문자열까지 견디는
스크립트를 씁니다. 각 규칙을 깨진 쪽과 고친 쪽을 나란히 두고 확인합니다.

환경

/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개

  1. 적대적인 이름 만들기
  2. 따옴표 하나로 인자 수가 바뀐다
  3. 줄로 세면 틀리고 NUL 로 세면 맞다
  4. 이름이 대시로 시작할 때
  5. 받은 인자를 그대로 넘기기
  6. 옵션 파서는 직접 만들지 않는다
  7. 입력은 값이지 코드가 아니다
  8. 다섯 규칙 정리