界: Code Quality

コードの質が低いと、予測できない動作につながります。ユーザーの視点には、それがしばしば使い勝手の悪さとなって現れます。攻撃者にとっては、予期せぬ方法でシステムにストレスを与える機会となります。

Code Correctness: Comparison of Boxed Primitive Types

Abstract
ボクシングされたプリミティブ型を、equals() メソッドではなく等価演算子を使用して比較すると、予期しない動作を引き起こす場合があります。
Explanation
ボクシングされたプリミティブ型が等価かどうかを比較する場合、演算子 ==!= ではなくボクシングされたプリミティブ型の equals() メソッドをコールするべきです。Java 仕様は、ボクシング変換について次のように記述しています。

"ボクシング変換の対象となる値 p が -128 から 127 までの数値であるint 型の整数リテラル、true または false のブール リテラル、「\u0000」から「\u007f」までの文字リテラルである場合、p に対する任意の 2 つのボクシング変換結果を a と b とする。この場合、常に a == b が成立する。"

これは、ボクシングされたプリミティブ型が使用される場合 (Boolean または Byte 以外)、特定の範囲の値のみがキャッシュまたはメモリに保存されることを意味します。値のサブセットでは、== または != を使用して正しい値を返します。このサブセットに含まれないすべての値では、オブジェクト アドレスを比較した結果を返します。

例 1: 次の例では、ボクシングされたプリミティブ型で等価演算子を使用しています。


...
Integer mask0 = 100;
Integer mask1 = 100;
...
if (file0.readWriteAllPerms){
mask0 = 777;
}
if (file1.readWriteAllPerms){
mask1 = 777;
}
...
if (mask0 == mask1){
//assume file0 and file1 have same permissions
...
}
...
Example 1 のコードでは、Integer のボクシングされたプリミティブ型を使用して、2 つの int 値を比較しようとしています。mask0mask1 が両方とも 100 と等しい場合は、mask0 == mask1true を返します。しかし、mask0mask1 が両方とも 777 に等しい場合は、これらの値がボクシングされたプリミティブ型のキャッシュされた値の範囲内にないため、mask0 == maske1false を返します。
References
[1] EXP03-J. Do not use the equality operators when comparing values of boxed primitives CERT
[2] Java Language Specification Chapter 5. Conversions and Contexts Oracle
[3] Standards Mapping - CIS Azure Kubernetes Service Benchmark 1
[4] Standards Mapping - CIS Amazon Elastic Kubernetes Service Benchmark 5
[5] Standards Mapping - CIS Amazon Web Services Foundations Benchmark 1
[6] Standards Mapping - CIS Google Kubernetes Engine Benchmark normal
[7] Standards Mapping - Common Weakness Enumeration CWE ID 398, CWE ID 754
[8] Standards Mapping - OWASP Application Security Verification Standard 4.0 11.1.7 Business Logic Security Requirements (L2 L3)
[9] Standards Mapping - SANS Top 25 2010 Risky Resource Management - CWE ID 754
desc.structural.java.code_correctness_comparison_of_boxed_primitive_types