2

特定のバイトコード命令でのみ発生するアプリケーション (soot を使用してバイトコードを処理する) のバグを特定しました。

その特定のケースのテストを作成したいと思います。ただし、期待されるバイトコードにコンパイルされるテストコードを確実に作成することはできません。これにより、バグがトリガーされます。

これは、バグをトリガーする私の試みです:

public void updateRhsOnIfEq() {
        int x = 15;
        int y = AircraftControl.readSensor(0);
        // FIXME != in bytecode instead of ==
        if (x == y) {
            AircraftControl.readSensor(y);
        }
        else {
            AircraftControl.readSensor(x);
        }
    }

問題は、コンパイラが比較を反転し、2 つの分岐を切り替えることによって分岐ロジックを変更することです。以下のバイトコードでわかるように、 の!=代わりに比較を行い==ます。ただし、私がテストしているバグは、==.

 public void updateRhsOnIfEq();
     0  bipush 15
     2  istore_1 [x]
     3  iconst_0
     4  invokestatic AircraftControl.readSensor(int) : int [17]
     7  istore_2 [y]
     8  iload_1 [x]
     9  iload_2 [y]
    10  if_icmpne 21 <============================== Should be if_icmpeq
    13  iload_2 [y]
    14  invokestatic AircraftControl.readSensor(int) : int [17]
    17  pop
    18  goto 26
    21  iload_1 [x]
    22  invokestatic AircraftControl.readSensor(int) : int [17]
    25  pop
    26  return

予測可能なバイトコードを簡単に生成する必要があるテスト ケースを作成する方法はありますか? さまざまなJavaコンパイラ、そのバージョンなどがある場合、これはまったく可能ですか?

4

3 に答える 3

2

コンパイラは分岐ロジックを変更しません。この場合、 if_icmpne を使用するのはコンパイラの自然な動作です (私の意見です)。(eclipse) コンパイラで を使用するif_icmpeqには、コードを次のように変更します。

if (x != y) {
    AircraftControl.readSensor(x);
}
else {
    AircraftControl.readSensor(y);
}

このコード:

public static void main(String[] args) {
    int x = (int) System.currentTimeMillis(), y = (int) System
            .currentTimeMillis();
    if (x != y) {
        System.out.println("x != y");
    } else {
        System.out.println("x == y");
    }
}

結果:

   0: invokestatic  #16     // Method java/lang/System.currentTimeMillis:()J
   3: l2i
   4: istore_1
   5: invokestatic  #16     // Method java/lang/System.currentTimeMillis:()J
   8: l2i
   9: istore_2
  10: iload_1
  11: iload_2
  12: if_icmpeq     26
  15: getstatic     #22     // Field java/lang/System.out:Ljava/io/PrintStream;
  18: ldc           #26     // String x != y
  20: invokevirtual #28     // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  23: goto          34
  26: getstatic     #22     // Field java/lang/System.out:Ljava/io/PrintStream;
  29: ldc           #34     // String x == y
  31: invokevirtual #28     // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  34: return
于 2013-05-15T13:33:25.067 に答える
2

特定のバイトコード命令が必要な場合、明白で最も信頼できる方法は、バイトコードで直接記述することです。

ここで入手できるオープンソースのアセンブラを作成しました。単純なケースでは、おそらくより適切に文書化されている Jasmin のようなものを使用できます。私は逆アセンブラも持っているので、微調整だけが必要な場合は、Java クラスをコンパイルし、逆アセンブルし、微調整してから再アセンブルするだけです。

于 2013-05-16T03:31:27.773 に答える