同じ名前のシェル関数と変数

同じ名前のシェル関数と変数

~からバッシュマニュアル:

同じ名前を持つシェル関数と変数は、シェルサブアイテムに渡される同じ名前を持つ環境に複数のアイテムを作成できます。これにより問題が発生する可能性がありますのでご注意ください。

bashは「シェル関数と同じ名前を持つ変数」をどのように区別しますか?

$  func () { return 3; }; func=4; declare -p func; declare -f func;
declare -- func="4"
func () 
{ 
  return 3
}

「環境で同じ名前を持つ複数の項目がシェルの子として渡される」場合はいつですか?

問題が発生したときに何に「注意」する必要がありますか?

ベストアンサー1

全体的な状況:独立した名前空間

通常、シェルは変数と関数が異なるコンテキストで使用されるため、これを区別します。簡単に言えば、名前はaの後に表示される$か、組み込み関数の引数として表示される場合(たとえばexport(without -f)やunset(without))、変数名です。-f名前は、コマンド(別名拡張後)または引数などで表示される場合の関数export -f名です。unset -f

変数を環境にエクスポートできます。環境変数は、シェル変数と同じ名前(および同じ値)を持ちます。

以前のbashの場合:関数のエクスポートによる混乱

他のほとんどのシェルとは異なり、Bashは機能を環境にエクスポートすることもできます。環境にはタイプマークがないため、環境内の項目が環境変数の名前または値を分析する以外に機能であるかどうかを識別する方法はありません。

以前のバージョンの bash では、関数名を名前として使用し、関数定義に似たものを関数値として使用して、環境に関数を保存しました。たとえば、

bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() {  echo foobar
}
bash-4.1$ 

{ echo foobar; }コードは、次の関数と値が次の変数() { echo foobar␤}(ここでは改行文字です)との間に違いはありません。これは誤った設計決定であることが判明した。

場合によっては、潜在的に敵対的なオブジェクトによって値が制御される環境変数を使用してシェルスクリプトが呼び出されます。たとえば、CGIスクリプトです。 Bashの関数のエクスポート/インポート機能を使用すると、この方法で関数を注入できます。たとえば、スクリプトを実行します。

#!/bin/bash
ls

環境に特定の名前(たとえば)を持つ変数が含まれていない限り、PATHリモート要求からの要求は安全です。しかし、リクエストが環境変数lsをに設定できる場合、それは関数の本文であるため、() { cat /etc/passwd; }bashはこれを喜んで実行します。cat /etc/passwdls

最新のbashの使用:はるかに混乱していません。

このセキュリティの脆弱性は、次のために発生します。スティーブン・チャジェラス片側にシェルショックバグ。 Shellshock以降のバージョンのbashからエクスポートされた関数は、次のように識別されます。名前内容よりも。

bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() {  echo foobar
}

BASH_FUNC_foobar%%同様の名前は通常コマンド名として使用されず、環境変数を渡すことができるインターフェイスを介してフィルタリングできるため、セキュリティ上の問題はありません。技術的には、%環境変数名に文字を含めることができます(これが現代bashのエクスポートされた関数が機能する理由です)。しかし、通常、シェルは%変数名を受け入れないため、人々はそうしません。

bashマニュアルのこの文は、以前(Shellshock以前)の動作を示しています。更新または削除する必要があります。最新のbashバージョンの場合は、環境変数名が%%

おすすめ記事