사용자가 입력한 횟수만큼 반복을 시도하는 동안 예기치 않은 출력이 나타나는 이유는 무엇입니까?

사용자가 입력한 횟수만큼 반복을 시도하는 동안 예기치 않은 출력이 나타나는 이유는 무엇입니까?

저는 이 bash 쉘 스크립트를 작성 중입니다:

#!/bin/bash

declare -i N
read N
for i in {1..$N}
do
  echo "Number: $i"
done

(나는 정수 declare -i N로 만든다고 믿는다 )N

그러나 이것을 실행하면 다음과 같은 결과가 나타납니다.

>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}

여기서는 사용자로부터 제한을 받아 루프를 실행하고 싶습니다.

답변1

에서 man bash:

확장 순서는 다음과 같습니다: 중괄호 확장; 물결표 확장, 매개변수 및 변수 확장, 산술 확장 및 명령 대체(왼쪽에서 오른쪽으로 수행됨) 단어 분리; 및 경로 이름 확장.

보시다시피 중괄호 확장이 먼저이므로 문제에서는 건너뛴 것 같습니다. 대신 다른 루프를 사용하겠습니다.

답변2

버팀대 확장의 문제점은 이미 지적되었지만 다음 사항만 언급하겠습니다.

(나는 선언 -i N이 N을 정수로 만든다고 믿습니다)

저는 그렇다고 대답하겠습니다. 그렇습니다. 명령 주입 취약점이 되기 때문에 문제가 됩니다. 해당 정수 속성을 설정하면 변수에 값이 할당될 때마다 해당 값이 산술 표현식으로 해석됩니다.

예를 들어 사용자가 a[$(reboot)]해당 read프롬프트에 입력하면 재부팅이 시도됩니다.

이는 산술 표현식이 평가될 때마다 발생하는 일반적인 문제 bash입니다 . ksh93 스타일 형식( 포함 여부와 상관없이 )을 사용하더라도 의 내용이 여전히 해당 산술적 맥락에서 평가되므로 문제가 될 수 있습니다.zshkshfor (( i = 1; i <= N; i++ ))declare -i NN

for i in {1..$N}declare -i Nksh, zsh 또는 yash -o braceexpand(횡설수설을 반복하지만 명령 주입 취약점을 유발하지 않음) 에서는 ( 없이) 괜찮을 것입니다. 또는 sh구현 shksh.

#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
  printf '%s\n' "Number: $n"
done

ksh[여전히 ​​의 피연산자를 산술 표현식으로 취급 -lt하므로 여전히 명령 주입 취약점이 발생합니다. 문제가 있는 / / 에는 [[ $i -lt $N ]]or를 사용하지 마십시오 .(( i < N ))bashzshksh

또는 루프를 수행하기 위해 적절한 프로그래밍 언어를 사용하거나 먼저 입력을 위생 처리할 수 awk있습니다 .perl

관련 정보