null ポインタ参照は、値が null である変数が、有効なオブジェクトを参照しているものとしてその状態が検査されずに参照されるときに発生する。この場合、NullPointerException が発生し、サービス運用妨害(denial-of-service)につながる可能性がある。したがって、プログラムは決して null ポインタを参照してはならない。
違反コード
以下の違反コード例は Reasoning によって最初に発見された Tomcat version 4.1.24 のバグを示している[Reasoning 2003]。cardinality メソッドは、col コレクションのなかに現れる obj オブジェクトの出現回数を返すように設計されたメソッドである。cardinality メソッドの正しい使い道の一つは、コレクションのなかにあるオブジェクトのいくつが null であるのかを調べることである。しかし、コレクションに含まれるメンバをチェックするには、式 obj.equals(elt) を使うことになるので、obj が null であり elt が null でない場合に null ポインタ参照が必ず発生する。
public static int cardinality(Object obj, final Collection col) { int count = 0; Iterator it = col.iterator(); while (it.hasNext()) { Object elt = it.next(); if ((null == obj && null == elt) || obj.equals(elt)) { // null ポインタ参照 count++; } } return count; }
適合コード
以下の適合コードでは null ポインタ参照を排除している。
public static int cardinality(Object obj, final Collection col) { int count = 0; Iterator it = col.iterator(); while (it.hasNext()) { Object elt = it.next(); if ((null == obj && null == elt) || (null != obj && obj.equals(elt))) { count++; } } return count; }
ここに示す明示的な null チェックは、null ポインタ参照を排除する有効なアプローチの一つである。
リスク評価
null ポインタ参照はサービス運用妨害(denial-of-service)につながる可能性がある。 マルチスレッドプログラムにおいては、null ポインタ参照はキャッシュコヒーレンシポリシー(cache coherency policies)に違反し、リソースリークを引き起こす可能性がある。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
EXP01-J | 低 | 高 | 高 | P3 | L3 |
自動検出
null ポインタ参照はプログラムの実行フローに依存して発生する場合がある。ツールによる自動検出には限界があるため、人の手によるコード分析が必要となる場合もあるだろう[Hovemeyer 2007]。メソッド引数に(この引数の値は null ではない、というような意味の)アノテーションをつけることで、検出ツールの処理を助け、人の手によるコード分析の必要性を減らすことができる。このようなアノテーションを行うことは強く推奨される。
関連する脆弱性
JDK 1.6 の update 4 より前のバージョンにおける Java Web Start アプリケーションとアプレットには、セキュリティ上重大な問題を引き起こすバグが存在した。場合によっては、アプリケーションやアプレットがサーバとの間で HTTPS 接続を確立しようとすることで NullPointerException が発生した[SDN 2008]。HTTPS によるセキュアな接続を確立できなかった結果、サービス運用妨害(denial-of-service)が発生した。クライアントはセキュアでない HTTP 接続による通信を一時的に行わざるを得なくなったのである。
関連ガイドライン
CERT C Secure Coding Standard | EXP34-C. Do not dereference null pointers |
CERT C++ Secure Coding Standard | EXP34-CPP. Ensure a null pointer is not dereferenced |
ISO/IEC TR 24772:2010 | "Null Pointer Dereference [XYH]" |
MITRE CWE | CWE-476. NULL Pointer Dereference |
参考文献
[API 2006] | method doPrivileged() |
[Hovemeyer 2007] | |
[Reasoning 2003] | Defect ID 00-0001 |
Null Pointer Dereference | |
[SDN 2008] | Bug ID 6514454 |
翻訳元
これは以下のページを翻訳したものです。
EXP01-J. Never dereference null pointers (revision 79)