シェルがスクリプト内のNULバイトを無視することを許可されていますか?

シェルがスクリプト内のNULバイトを無視することを許可されていますか?

なぜなら彼らの一部がそうしているからです。

> echo echo Hallo, Baby! | iconv -f utf-8 -t utf-16le > /tmp/hallo
> chmod 755 /tmp/hallo
> dash /tmp/hallo
Hallo, Baby!
> bash /tmp/hallo
/tmp/hallo: /tmp/hallo: cannot execute binary file
> (echo '#'; echo echo Hallo, Baby! | iconv -f utf-8 -t utf-16le) > /tmp/hallo
> bash /tmp/hallo
Hallo, Baby!
> mksh /tmp/hallo
Hallo, Baby!
> cat -v /tmp/hallo
#
e^@c^@h^@o^@ ^@H^@a^@l^@l^@o^@,^@ ^@B^@a^@b^@y^@!^@
^@

これは実際に互換性の問題ですか?必須標準的に?かなり危険で予期せぬように見えるからです。

ベストアンサー1

~によるとPOSIX

入力ファイルはテキストファイルでなければなりませんが、行の長さは制限されません。^

入力のNUL文字²テキストではないものにする、POSIXに関する限り動作は指定されていないので、sh実装は必要に応じて何でも行うことができます(そしてPOSIXと互換性があります)。スクリプトNULを含めることはできません)。

一部のシェルは、最初の数バイトからゼロを検索し、誤ってスクリプトではなくファイルを実行しようとすると、スクリプトの実行を拒否します。

exec*p()これは関数、envコマンドshfind -exec...のために便利です。必須システムがENOEXECを返すと、コマンドを解釈するためにシェルが呼び出されますexecve()。したがって、間違ったアーキテクチャに対してコマンドを実行したい場合は、次のようにするのが最善です。バイナリは実行されません。シェルで発生するファイルエラーは、それをシェルスクリプトとして理解しようとするシェルの試みで発生したエラーではありません。

これはPOSIXで許可されています。

実行可能ファイルがテキストファイルではない場合、シェルはこのコマンドの実行をバイパスできます。

本規格の次の改訂版ではに変更されます:

シェルは、実行されるファイルがスクリプトであるかどうかを判断するために経験的チェックを適用することができ、ファイルがスクリプトでないと判断した場合は、このコマンドの実行をバイパスできます。この場合、エラーメッセージを作成して終了ステータス126を返す必要があります。
注:スクリプトにできないファイルを拒否する一般的な経験的な方法は、固定長内の<newline>バイトの前にNULバイトファイルプレフィックスを置くことです。 shは行の長さが無制限の入力ファイルを許可する必要があるため、経験的チェックは行の長さに基づいて行うことはできません。

この動作により、アーカイブにシェルヘッダーとバイナリデータが含まれていても、シェルの自動抽出アーカイブを防ぐことができます。

シェルはzsh入力でNULをサポートしますが、NULはの引数として渡すことはできないため、その引数または名前execve()にのみ使用できます。組み込みコマンドまたは機能:

$ printf '\0() echo zero; \0\necho \0\n' | zsh | hd
00000000  7a 65 72 6f 0a 00 0a                              |zero...|
00000007

(ここでは、NULを名前として関数を定義して呼び出し、NUL文字を組み込みコマンドechoの引数として渡します。)

皮をむく人もいるが、それも賢明なことだ。NULsは時々フィラーとして使用されます。たとえば、端末では無視されます (キャリッジ リターン (文字通り) などの複雑な制御シーケンスを処理する時間を持つために端末に送信される場合もあります)。ファイルの穴はNULなどで埋められているようです。

非テキストは NUL バイトに限定されません。また、ロケールで有効な文字を形成しないバイト列でもあります。たとえば、0xc1バイト値はUTF-8でエンコードされたテキストには表示できません。したがって、文字エンコーディングとしてUTF-8を使用するロケールでは、これらのバイトを含むファイルは有効なテキストファイルではなく、有効なshスクリプトでもありません。

実際に、yashこれは私がこのような誤った入力について文句を言う唯一のシェルです。


1 この規格の次の改訂版ではそれは変わるでしょう到着

入力ファイルは任意のタイプにすることができますが、シェル構文(XREF - XSH 2.10.2シェル構文規則)に基づいて解析されるファイルの初期部分は文字で構成する必要があり、NUL文字を含めないでください。シェルは行長制限を適用しないでください。

自己抽出アーカイブを説明するために残りの部分にNULが含まれていても、NULバイトなしで有効な構文部分で始まる入力をサポートするには、シェルが明示的に必要です。

²と文字は、ロケールの文字エンコーディング(出力を参照locale charmap)に従ってデコードされるようになっており、POSIXシステムでは、NUL文字(エンコーディングは常にバイト0)は、エンコードにバイト0を含む唯一の文字です。つまり、UTF-16はPOSIXロケールで使用できる文字エンコーディングではありません。

LANG3 ただし、スクリプト内で(たとえば// /変数を割り当てると)ロケールの変更に問題があり、LC_CTYPE変更が入力を解釈するシェルに適用されることがあります。LC_ALLLOCPATH

おすすめ記事