Java における唯一の符号無しプリミティブ整数型は16ビット char 型である。その他のプリミティブ整数型はすべて符号付きである。符号無し型を活用する C や C++ のようなネイティブ言語とやりとりするには、想定される符号無しデータの値の範囲をすべて表現できるような Java の整数型を使って、値の読み取りや保存を行わなくてはならない。たとえば、ネイティブコードから取得した符号無し32ビット整数のすべての値を表現するには、Java の long 型を使う。
違反コード
以下の違反コード例では、元のデータの符号属性を考慮せずに整数データを読み込んでいる。この場合、読み込んだデータは符号付きデータであるとみなされ、最上位ビットは符号ビットとして扱われる。元のデータが符号無しデータだった場合、符号と絶対値の解釈を間違ってしまう。
public static int getInteger(DataInputStream is) throws IOException { return is.readInt(); }
適合コード
以下の適合コードでは、読み込むデータを32ビット符号無し整数であるとする。readInt() メソッドを使って符号無し整数値を読み込んでいるが、このメソッドは読み込む値が符号付きであると仮定し、Java の符号付き整数型 int の値を返す。この値は符号拡張により long 型に格上げされる。& 演算により上位32ビットがマスクされ、その結果、32ビット符号無し整数の範囲の値が得られる。マスクするサイズは読み込む符号無し整数のサイズに合せて決めること。
public static long getInteger(DataInputStream is) throws IOException { return is.readInt() & 0xFFFFFFFFL; // 上位32ビットを0にする }
一般に、読み込むデータの符号属性には注意すべきである。
リスク評価
符号無しデータを符号付きデータとして扱うと、データの欠損や誤解釈を招くことがある。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
NUM03-J | 低 | 低 | 中 | P2 | L3 |
自動検出
一般に、自動検出は不可能である。
参考文献
[API 2006] | Class DataInputStream: method readInt |
[Harold 1997] | Chapter 2: Primitive Data Types, Cross Platform Issues, Unsigned Integers |
[Hitchens 2002] | 2.4.5 Accessing Unsigned Data |
翻訳元
これは以下のページを翻訳したものです。
NUM03-J. Use integer types that can fully represent the possible range of unsigned data (revision 58)