[著]文字列操作に関するプログラミングエラーはいくつかありますが、今回は基本的であるが間違いを犯しやすい文字列のNULL終端エラーについて解説します。文字列は、プログラムとユーザ、プログラムとプログラム間のインタフェースとして利用されるのをはじめ、XMLなどテキスト形式で表現された情報を処理する際にも利用されます。データのみならず、プログラムの挙動に直接影響する動作パラメタや設定情報など様々な情報がテキスト形式で表現されるにつれ、文字列を処理する機会が増加すると共に、文字列を処理すること自体の重要性が高まっています。攻撃者にしてみれば、プログラムの挙動を操作しうる文字列処理の不備を突く機会も多く存在することになるため、文字列操作エラーを作り込まないことが求められます。文字列操作に関するプログラミングエラーはいくつかありますが、今回は基本的であるが間違いを犯しやすい文字列のNULL終端エラーについて解説します。文字列型を持たないC言語において、文字列は文字型の配列で表現されます。この配列には、文字列の最後を示すNULL文字が含まれている必要があります。文字列用に確保された文字型配列内にNULL文字が含まれていなければ、文字列として不完全であり、文字列を取り扱う関数や処理に引き渡した場合、脆弱性の要因となります。以下にNULL終端エラーに関連したいくつかの脆弱性の事例を示します。)は、米国政府の支援を受けた非営利団体MITRE社が採番している識別子です。終端文字に依存する処理C標準の文字列処理関数を用いて文字列操作を安全に行うためには、引数として渡す文字列が確実にNULL終端されている必要があります。これは、strcpy()やstrlen()などをはじめとするC標準の文字列処理関数の動作が、NULL終端文字に依存しているためです。strlen()は、引数として渡された文字列にNULL終端文字が出現するまでの文字数をカウントしますし、strcpy()は、コピー先バッファにNULL終端文字が見つかるまで、コピー元の文字列の内容を書き込みます。C標準の文字列処理関数を利用していない場合でも、以下に示すコード例のように、NULL終端文字の存在に依存したコードを書くこともあるでしょう。*/}このコード例においても、ループの終了条件を満たすためには、処理対象となる文字列がNULL終端されている必要があることが分かります。いったケースは、バッファーオーバーフローの発生や、その他の未定義動作につながる恐れがあります。上記のコード例であれば、配列の境界を越えて書き込みが行われ、メモリ内の他のデータを破壊してしまいます。strlen()であれば、想定される文字列の長さよりも、より大きな値が返却され、後続の処理でバッファーオーバーフローが引き起こされることも考えられます。NULL終端を確実に行うNULL終端エラーを作りこまないためには、プログラマが責任を持ち、文字列がNULL終端されていることを確認するか、または自らNULL終端した上で、NULL終端文字の存在に依存する処理へ制御を移さなければなりません。前述のコード例であれば、ループに入る前に配列の最後をNULL終端することで、元の配列にNULLが含まれていない場合でも、ループの終了条件を確実に満たすことができます。TR24731で提案されWindowsで利用可能なstrcpy_s()や、OpenBSD、FreeBSD、Solarisなどで利用可能なstrlcpy()など)を利用することもできます。*/}こういった対策は、NULL終端文字に依存するC標準の文字列処理関数へ文字列を引数として渡す場合においても同様です。NULL終端文字を直接設定するか、あるいは、NULL終端された文字列を作成する関数を利用することになります。strlen(ntbs);返り値の文字列がNULL終端されているとは限らない文字列処理関数の利用に注意また、返り値の文字列が必ずしもNULL終端されているとは限らない、C標準の文字列処理関数strncpy()の利用において、プログラマ自身が間違いを犯さないようにしなければなりません。strlen()に渡す危険があります。strlen(ntbs);strncpy()は、最大指定されたコピー文字数分を、コピー元配列からコピーしますが、コピーの過程でNULL文字が出現した場合は、その時点で、コピーを終了します。NULL文字が現れなかった場合は、指定された文字数分のみコピーを行います。この場合、strncpy()によって返される文字列は、NULL終端されていません。よって、プログラマは、strncpy()が返す文字列が、NULL終端されないケースがあることを認識した上で、適切に対応する必要があります。strlen(ntbs);strncpy()のように誤用されやすい関数の利用以外にも、realloc()関数を利用して、バッファサイズの縮小を行った際にNULL終端を怠ってしまうケースや、memset()関数で事前にコピー先バッファにNULL文字をセットしたが、文字データをコピーする際に誤ってバッファの最終NULL文字を上書きしてしまうケースなどのうっかりミスにも注意が必要です。NULL終端文字列を作成するということは、単純なことではありますが、文字列がNULL終端されていることに依存する処理を安全かつ正確に実行させ、プログラムを意図した通りに動作させるためには必要不可欠です。いいえその他、ご意見・ご感想などございましたら、ご記入ください。こちらはご意見・ご感想用のフォームです。各社製品については、各社へお問い合わせください。※本フォームにいただいたコメントへの返信はできません。javascriptを有効にすると、ご回答いただけます。ありがとうございました。