JPCERT コーディネーションセンター

STR01-C. 文字列の管理は一貫した方法で行う

C のプログラムで文字列を管理するには、2 つの基本的な方法がある。静的に割り当てた配列に文字列を保持する方法と、必要に応じて動的にメモリを割り当てる方法である。どちらの方法にも一長一短があるが、一般に、文字列管理の方法を 1 つ選び、プロジェクト全体を通して一貫して同じ方法を採用するのがよい。同じ方法を採用しなければプログラマ個人に判断が委ねられ、一貫性のないさまざまな選択がなされる可能性がある。

静的に割り当てられた文字列は、固定サイズの文字配列を想定しており、バッファが満たされた後はデータを追加することができない。静的な方法ではバッファを超過したデータを破棄するため、プログラムの実データが失われる可能性がある。そのため、得られた文字列の妥当性を十分に確認する必要がある。

動的に割り当てられたバッファは、メモリ領域が不足するたびに動的にサイズが変わる。動的な方法は拡張性が高く、バッファを超過したデータが破棄されることもない。主な短所は、入力が制限されていない場合にマシン上のメモリを使い果たし、結果としてサービス運用妨害(DoS)攻撃に使われる可能性があることである。

動的な割り当ては、安全性が要求されるシステムでは許容されないことが多い。たとえば、MISRA 標準は、「動的なヒープメモリ割り当ては使用してはならない」と規定している [MISRA 2004] 。安全性が要求されるシステムの中には、初期化中には動的メモリ割り当てができるが、稼動中にはできないものもある。たとえば、航空用ソフトウェアは、航空機の初期化中に動的メモリを割り当てることはできるが、飛行中にはできない。

文字列データの管理に利用できる既存のライブラリがいくつかある。どのライブラリを選択するかは null 終端バイト文字列の管理方法によって異なる。C 標準のセクション 7.24 で定義されている関数は、主に静的に割り当てられた文字列を管理することを目的としている。ただし、これらの関数の多くは境界指定が不十分なため、問題がある。このため、静的に割り当てられた配列には、ISO/IEC TR 24731-1 [ISO/IEC TR 24731-1:2007] の関数を使用することが推奨される(「STR07-C. 境界チェックインタフェースを使用し、文字列操作を行う既存のコードの脅威を緩和する」を参照)。これらの関数は、バッファオーバーフローや他の実行時制約違反を防ぐための境界チェックインタフェースを提供している。

ISO/IEC TR 24731-2 では、別の方法として、処理結果に対して十分なメモリを割り当てる関数を提案している [ISO/IEC TR 24731-2]。ここでは、文字列関数の結果を必要に応じて動的に割り当てる API を規定している。この技術文書にあるほとんどすべての API は、現在の国際標準にも含まれている。たとえば、TR 24731-2 に含まれている関数には strdup() [ISO/IEC 9945:2003] などの POSIX 関数と、asprintf() [ISO/IEC 23360-1:2006] などの Linux Standard Base Core Specification の関数がある。

リスク評価

アプリケーション内で一貫した文字列管理方法を採用しないと、一貫性のない決定がなされ、安全性の要件への適合などのシステム特性を保証することが難しくなる。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

STR01-C

P1

L3

関連するガイドライン
CERT C++ Secure Coding Standard STR01-CPP. Adopt and implement a consistent plan for managing strings
ISO/IEC TR 24731-1:2007  
ISO/IEC TR 24731-2:2010  
MISRA-C Rule 20.4
参考資料
[CERT 2006c]  
[ISO/IEC 9945:2003]  
[ISO/IEC 23360-1:2006]  
[Seacord 2013] Chapter 2, "Strings"
翻訳元

これは以下のページを翻訳したものです。

STR01-C. Adopt and implement a consistent plan for managing strings (revision 74)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter