작업 디렉터리에 괄호/대괄호가 있는 파일로 인해 평가 오류가 발생함

작업 디렉터리에 괄호/대괄호가 있는 파일로 인해 평가 오류가 발생함

오늘 괄호 안에 있는 디렉터리가 포함된 디렉터리에서 스크립트를 실행할 때 이상한 오류가 발생했습니다 a().

최소한의 작업 예

다음과 같은 최소한의 작업 예제로 오류를 줄였습니다.

/tmp그 안에 빈 디렉터리를 만듭니다 cd.

mkdir /tmp/foo
cd /tmp/foo

라는 파일을 만듭니다.foo.sh여기에는 다음이 포함됩니다.

foo() {
  somevar=1;
  case somevar in
      aha) echo "something" ;;
      *) echo "other" ;;
  esac;
};

다음 명령을 실행하십시오.

eval $(/bin/cat foo.sh)

오류가 있어서는 안 됩니다.

대괄호로 묶인 파일을 만듭니다.

touch "a()"

명령을 다시 실행하십시오.

eval $(/bin/cat foo.sh)

이제 오류가 발생합니다.

bash: syntax error near unexpected token `(' 

Bash는 왜 디렉토리에 어떤 파일이 있는지 신경을 쓰나요? 괄호로 인해 오류가 발생하는 이유는 무엇입니까?

시스템 메시지:

$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:        18.04
Codename:       bionic

더 자세한 배경 및 원래 오류:

/usr/share/modules/init/bash내 문제는 아래에 요약된 패키지의 스크립트를 사용하는 데서 발생합니다 environment-modules.

$ dpkg -l environment-modules 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                                          Version                             Architecture                        Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii  environment-modules                                           4.1.1-1                             amd64                               Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'

답변1

이것은 놀라운 일도 아니고 버그도 아닙니다 bash(물론 버그인 것 같지만 /usr/share/modules/init/bash). 따옴표가 없는 명령을 로 대체합니다 eval. 명령 대체의 결과인 문자열은 따옴표가 없기 때문에 단어 분할 및 파일 이름 확장(와일드카드)이 됩니다. 코드에서 *)filename 과 일치하므로 a()파일 이름 확장 단계에서 해당 파일 이름으로 대체됩니다.

아래 예제를 실행하면 set -x다음이 강조됩니다.

$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('

쉘에서도 마찬가지입니다 yash.

$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing

그리고 ksh93:

$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected

그리고 dash:

$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")

zshGlobbing을 수행하지 않기 때문에 Only가 이를 처리합니다.

$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'

이 문제를 처리하는 올바른 방법은원천스크립트 foo.sh:

. ./foo.sh

eval "$(cat foo.sh)"제가 아는 한, 실제로 사용할 이유가 없습니다.

이는 코드 주입 취약점이기도 합니다.

$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
    somevar=1;
    case somevar in
        aha)
            echo "something"
        ;;
        *)
            echo "hello"
        ;;
        *)
            echo "other"
        ;;
    esac
}

이 명령을 쉽게 중단하는 또 다른 방법아니요IFS변수를 기본 문자 집합 외부의 문자 집합으로 설정하여 특별히 이름이 지정된 파일을 만듭니다 .

$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'

evaluse 를 평가할 때 IFS=';{} '각 문자가 텍스트를 단어로 분할하는 데 사용되기 때문에 문제가 발생합니다 foo.sh(해당 문자는 문자열에서 제거됩니다).

심지어 다음에 도 zsh면역이 되지 않습니다:

$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'\n' 'somevar=1' $'\n' case somevar $'in\n' 'aha)' echo '"something"' '' $'\n' '*)' echo '"other"' '' $'\n' esac $'\n' '' ''
zsh: parse error near `)'

관련된:

관련 정보