コードの質が低いと、予測できない動作につながります。ユーザーの視点には、それがしばしば使い勝手の悪さとなって現れます。攻撃者にとっては、予期せぬ方法でシステムにストレスを与える機会となります。
getChunk
であるため、述部 getChunk == NULL
は常に false になります。
if (getChunk == NULL)
return ERR;
char* getName() {
char name[STR_MAX];
fillInName(name);
return name;
}
class AccessLevel{
public static final int ROOT = 0;
//...
public static final int NONE = 9;
}
//...
class User {
private static int access;
public User(){
access = AccessLevel.ROOT;
}
public static int getAccessLevel(){
return access;
}
//...
}
class RegularUser extends User {
private static int access;
public RegularUser(){
access = AccessLevel.NONE;
}
public static int getAccessLevel(){
return access;
}
public static void escalatePrivilege(){
access = AccessLevel.ROOT;
}
//...
}
//...
class SecureArea {
//...
public static void doRestrictedOperation(User user){
if (user instanceof RegularUser){
if (user.getAccessLevel() == AccessLevel.ROOT){
System.out.println("doing a privileged operation");
}else{
throw new RuntimeException();
}
}
}
}
getAccessLevel()
をインスタンス user
にコールしているのであって、クラス User
や RegularUser
にコールしているのではないため、この場合は常に true
が返され、instanceof
が使用される場合でも、if/else
ブロックのこの部分に到達するために操作が制限されます。serialPersistentFields
を正しく使用するには、private
、static
、および final
として宣言する必要があります。serialPersistentFields
配列内で指定して、クラスの Serializable フィールドを手動で定義できるようになります。この機能は、serialPersistentFields
が private
、static
、および final
として宣言されている場合にのみ奏功します。serialPersistentFields
が、private
、static
、および final
ではないため、Serializable
フィールドの定義には使用されません。
class List implements Serializable {
public ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("myField", List.class) };
...
}
java.util.Arrays.equals().
ではなく Object.equals()
をコールしています。 Object.equals()
をコールすることは、多くの場合誤りです。この関数は配列の要素ではなく配列のアドレスが等価かどうかをチェックするため、通常は java.util.Arrays.equals()
で置き換える必要があります。 Object.equals()
関数を使ってチェックしようとしています。
...
int[] arr1 = new int[10];
int[] arr2 = new int[10];
...
if (arr1.equals(arr2)){
//treat arrays as if identical elements
}
...
pthread_cleanup_push()
を使用して、関数 routine
をコールしたスレッドのクリーンアップスタックにプッシュして戻っています。pthread_cleanup_push()
およびそのパートナ関数 pthread_cleanup_pop()
が IBM AIX 以外のプラットフォームではマクロとして実装されているため、pthread_cleanup_push()
で作成されるデータ構造は、pthread_cleanup_pop()
への後続のコールで利用できなくなります。このコードは、これらの関数がマクロとして実装されているすべてのプラットフォームでコンパイルに失敗するか、あるいは、ランタイム時の動作が不正となります。
void helper() {
...
pthread_cleanup_push (routine, arg);
}
void clean_up()
{
char tmp[256];
...
free(tmp);
return;
}
System.Object.Equals()
を上書きするためのものです。
public boolean Equals(string obj) {
...
}
System.Object.Equals()
は、object
タイプの引数を取るため、メソッドがコールされることはありません。Object.equals()
を上書きするためのものです。
public boolean equals(Object obj1, Object obj2) {
...
}
Object.equals()
は単一引数のみを受け取るため、Example 1
のメソッドがコールされることはありません。ISerializable
インターフェイスを実装しているが、[Serializable]
属性を宣言していないクラスはシリアライズされません。[Serializable]
属性が宣言されているすべてのオブジェクトのシリアライズを許可します。.NET フレームワークにより定義されるデフォルトのシリアライズメソッドを使用してクラスがシリアライズ可能な場合、オブジェクトを正しくシリアライズするためにこれは必要十分条件となります。クラスで独自のシリアライズメソッドが必要となる場合には、ISerializable
インターフェイスを実装する必要もあります。ただし、クラスは [Serializable]
属性をここでも宣言する必要があります。CustomStorage
クラスは ISerializable
インターフェイスを実装します。しかし、このクラスは [Serializable]
属性を宣言していないため、シリアライズされません。
public class CustomStorage: ISerializable {
...
}
java.io.Serializable
を実装している内部クラスは、問題が発生したり、外部クラスから情報が漏えいする可能性があります。
...
class User implements Serializable {
private int accessLevel;
class Registrator implements Serializable {
...
}
}
Example 1
では、内部クラス Registrator
がシリアライズされると、外部クラス User
からのフィールド accessLevel
もシリアライズされます。synchronized
を宣言した親クラスは、複数のスレッドが同じインスタンスにアクセスするときに、正しい動作を保証します。すべての上書きメソッドを、synchronized
として宣言する必要があります。そうしないと、予期せぬ動作が発生する可能性があります。Foo
がクラス Bar
を上書きしていますが、メソッド synchronizedMethod
を synchronized
に宣言していません。
public class Bar {
public synchronized void synchronizedMethod() {
for (int i=0; i<10; i++) System.out.print(i);
System.out.println();
}
}
public class Foo extends Bar {
public void synchronizedMethod() {
for (int i=0; i<10; i++) System.out.print(i);
System.out.println();
}
}
Foo
のインスタンスが、タイプ Bar
にキャストされる可能性があります。同じインスタンスが 2 つのスレッドに指定されており、synchronizedMethod
が繰り返し実行される場合、動作が予期できなくなります。obj.Equals(null)
は常に false となります。Equals()
メソッドを使用してオブジェクトを null
と比較します。Equals()
メソッドのコントラクトでは、この比較で常に false が戻される必要があります。obj.equals(null)
は常に false となります。equals()
メソッドを使用してオブジェクトを null
と比較します。オブジェクトが null
ではないため、この比較は常に false を返します。(オブジェクトが null
の場合、プログラムは NullPointerException
を発生させます)。pthread_exit()
をコールせずに生成されたスレッドより前に親プロセスが実行を終了すると、親プロセスの main()
関数から pthread_create()
をコールして生成されたスレッドは予定より早く終了します。pthread_exit()
をコールすることで、親プロセスのすべてのスレッドが実行を完了するまで親プロセスが終了せずに実行しつづけることを保証できます。または、親プロセスはすべての子スレッドで pthread_join
をコールして、プロセスが終了する前に確実に子スレッドが完了するようにできます。pthread_create()
を使用して、スレッドを作成して正常に終了しています。main()
関数が戻るときまでに、子スレッドがその実行を終了していない場合は、予定より早く実行を終了することになります。
void *Simple(void *threadid)
{
...
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
int rc;
pthread_t pt;
rc = pthread_create(&pt, NULL, Simple, (void *)t);
if (rc){
exit(-1);
}
}
readObject()
メソッドは、オーバーライドされる可能性のある関数を呼び出します。readObject()
は、コンストラクターのように振る舞うため、オブジェクトの初期化は関数が終わるまで完了しません。そのため、Serializable
の readObject()
関数がオーバーライド関数をコールすると、完全に初期化される前にオブジェクトの状態にオーバーライド メソッドがアクセスできるようになります。readObject()
関数は、オーバーライドされる可能性のあるメソッドをコールしています。
...
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
checkStream(ois);
ois.defaultReadObject();
}
public void checkStream(ObjectInputStream stream){
...
}
checkStream()
と括弧で囲まれたクラスは final
ではなくパブリックであるため、関数がオーバーライドできるようになります。つまり、攻撃者は checkStream()
関数をオーバーライドし、デシリアライゼーションの間、オブジェクトにアクセスできるようになります。private readonly
リスト変数を getter-only プロパティから戻すと、呼び出し元のコードはリストのコンテンツを変更でき、実質的にリストに書き込みアクセスを許可するので、private readonly
としたプログラマの意図に反します。private readonly
として宣言されたリスト _item
が含まれます。
class Order
{
private readonly List<string> _item = new List<string>();
public IEnumerable<string> Item { get { return _item; } }
public Order()
{
/*class initialize */
}
/*some important function......*/
}
Marker child = MarkerManager.getMarker("child");
Marker parent = MarkerManager.getMarker("parent");
child.addParents(parent);
parent.addParents(child);
String toInfinity = child.toString();
toString()
を子が呼び出すと、スタック オーバーフロー例外 (スタック枯渇) がトリガーされます。この例外は、子と親の間の循環リンクが原因で発生します。String
オブジェクトの比較は、信頼できないため、実行しないでください。String
オブジェクトと比較するには、まず String
オブジェクトに変換します。通常、Double.toString()
のような関数を使います。浮動小数点の変数のタイプと値により、String
オブジェクトに変換すると、結果は "NaN"、"Infinity"、"-Infinity"、ゼロを含む一定の小数値を持つ値、または指数フィールドを含む値になる場合があります。16 進数の String に変換された場合も、表現が大幅に異なることがあります。String
と比較しています。
...
int initialNum = 1;
...
String resultString = Double.valueOf(initialNum/10000.0).toString();
if (s.equals("0.0001")){
//do something
...
}
...
if
ステートメントで条件が満たされることはありません。変数 s
には NULL 以外の値が求められていますが、一方で、s
に NULL 以外の値を割り当てることができるパスには、return
ステートメントが記述されています。
String s = null;
if (b) {
s = "Yes";
return;
}
if (s != null) {
Dead();
}