Skip to content

CGCL-codes/InterFuzz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InterFuzz

InterFuzz is a fuzzing tool designed to systematically generate Java test cases with complex inter-class structures. InterFuzz introduces a novel concept of Heterogeneous Program Graph (HPG) to abstract and manipulate inter-class relationships. It then employs Inter-Class Mutators to construct intricate interactions, and utilizes Graph Complexity to guide test generation toward high-diversity code. Our evaluation shows that InterFuzz effectively uncovers compiler bugs that elude traditional fuzzers, having discovered 24 new bugs across HotSpot, ART, and R8. Among these, 20 bugs are confirmed by developers and 16 bugs hinge on intricate inter-class structures.

Installation & Usage

  1. Prepare target Java optimizing compiler
  2. Install Java as environment for InterFuzz
    sudo apt update && apt install -y openjdk-17-jdk
  3. Download InterFuzz and seeds from repository
  4. Run InterFuzz with the following command:
    java -jar InterFuzz.jar [-jdk <arg>] [-seeds_path <arg>] [-target_seed <arg>] [-max_iter <arg>]
    Example Command:
    java -jar InterFuzz.jar --seeds_path seeds/JavaFuzzer/  --target_seed Test0001 --jdk path/to/targetJavaCompiler1/bin/,path/to/targetJavaCompiler2/bin/ --max_iter 400

Design of Inter-Class Mutator

In this work, we design a set of Inter-Class Mutators to systematically generate Java test cases with complex inter-class structures. These mutators work by expanding the Heterogeneous Program Graph (HPG) to create compilex inter-class structures, and are categorized into two types: mutators for adding nodes and mutators for adding edges.

  • Mutators for Adding Node
    • Add Class Node
      This mutator adds a new class node (e.g. classes C0) to the HPG, creating a new class in the program without any inter-class structures. While adding a node to the HPG does not directly create inter-class structures, it provides essential building blocks for structures. In subsequent mutations, InterFuzz can apply other mutators to the new class C0.
    • Add Interface Node
      This mutator adds a new interface node (e.g., interface I0) to the HPG. This corresponds to creating a new interface in the program. Similar to adding a class node, this provides a necessary component for subsequent mutations, such as adding implementation or inheritance edges.
    • Add Method Node
      This mutator selects an existing class or interface node (e.g., C0) and adds a new method node to it. In the source code, this translates to declaring a new method within the scope of class C0. This new method serves as a target for subsequent mutations, such as creating method calls (Reference between classes or interfaces).
    • Add Field Node
      This mutator selects an existing class node (e.g., C0) and adds a new field node to it. This corresponds to declaring a new member variable (field) in the source code of class C0. Fields are fundamental to a class's state and are prerequisites for creating Reference edges (e.g., a field in one class referencing an object of another).
  • Mutators for Adding Edge
    • Add Inheritance Edge
      This mutator is designed to introduce Inheritance structures into a program. InterFuzz selects two compatible nodes (classes C1 and C2) and connects them with an Inheritance edge, which translates to an extends declaration in the source code.
    • Add Interface Implementation Edge
      This mutator is designed to introduce Interface Implementation structures. InterFuzz selects a class node C1 and an interface node I1 and connects them with an Interface Implementation edge. This translates to adding an implements keyword to the declaration of class C1 in the source code.
    • Add Nesting Edge
      This mutator is designed to create Nesting structures. It models this as a code refactoring operation on the HPG, represented by adding a directed nesting edge from an "outer" class to an "inner" class. For instance, adding an edge from C1 to C2 corresponds to restructuring the source code, transforming class C2 into a nested type within the scope of class C1.
    • Add Generic Bounds Edge
      This mutator introduces Generic Bounds structures. It selects a generic type parameter (e.g., T) and a class or interface node (e.g., C1) to serve as its bound. It then adds a Generic Bounds edge, which translates to a bounded type parameter like <T extends C1> in the source code.
    • Add Reference Edge This mutator is designed to create Reference structures, representing a dependency or association. InterFuzz selects two nodes (e.g., C1 and C2) and adds a directed Reference edge from C1 to C2. In the source code, this typically translates to C1 invoke methods defined in C2, access fields in C2, or create objects of C2.

Detected Bugs

InterFuzz has discovered 24 new bugs across three major Java compilers: HotSpot (4 bugs), ART (7 bugs), and R8 (13 bugs). Among these, 20 bugs have been confirmed by developers, with 13 bugs already fixed. The table below provides a detailed breakdown of all detected bugs, including their symptoms, current status, whether they are related to inter-class structures, and priority levels.

No. Bug ID Compiler Symptom Status Inter-Class
Related
Priority
1 8357782 HotSpot Semantic Error Fixed P3
2 8361699 HotSpot Crash Fixed P3
3 8357381 HotSpot Crash Confirmed P3
4 8357242 HotSpot Semantic Error Duplicate P4
5 405152615 ART Semantic Error Fixed P2
6 418897611 ART Semantic Error Confirmed P2
7 369670481 ART Semantic Error Confirmed P3
8 369739225 ART Semantic Error Confirmed P3
9 405149431 ART Semantic Error Confirmed P3
10 410253904 ART Semantic Error Confirmed P3
11 405149432 ART Semantic Error Duplicate P3
12 412524379 R8 Crash Fixed P1
13 419464490 R8 Crash Fixed P1
14 379347946 R8 Semantic Error Fixed P1
15 420228751 R8 Semantic Error Fixed P2
16 367915233 R8 Semantic Error Fixed P2
17 426351560 R8 Semantic Error Fixed P2
18 418719343 R8 Semantic Error Fixed P2
19 419404081 R8 Semantic Error Confirmed P2
20 372806451 R8 Semantic Error Duplicate P2

Case Study for detected bugs

Issue 8357782 in HotSpot

  • Bug Link: https://bugs.openjdk.org/browse/JDK-8357782
  • Symptom: Semantic Error
  • Status: Fixed
  • Priority: P3
  • Test Case:
    class C2 {
      class C3 {
        static String field;
        static void foo() {
          new C4(field);
        }
      }
      static class C4 {
        static { C3.field = "Hello"; }
        C4(String arg1) {
          System.out.print(arg1);
        }
      }
    }
    class C1 {
      public static void main(String[] args) {
        C2.C3.foo();
      }
    }

This bug's root cause is a faulty optimization in the JVM's JIT compiler that fails to handle side effects within Reference inter-class structure. The code establishes a critical reference where the static initializer of class C4 modifies a static field in class C3. The JIT compiler's optimization pass fails to recognize this inter-class interaction. When compiling the C2.C3.foo() method, it reads the initially null value of C2.C3.field for the constructor argument. It then incorrectly assumes the new C4() operation has no side effects on this field, failing to account for the fact that this operation's own static initializer is what assigns "Hello" to the field. As a result, the faulty optimization uses the stale null value, causing the incorrect output. The bug is triggered directly by the compiler's inability to track state changes across these tightly-coupled class structures.

Issue 426351560 in R8

  • Bug Link: https://issuetracker.google.com/issues/426351560
  • Symptom: Semantic Error
  • Status: Fixed
  • Priority: P2
  • Test Case:
    public class C1 implements I {
      public void foo2() {
        System.out.println("Cr.foo2()");
      }
    }
    interface I {
      default String foo() {
        System.out.println("I.foo2()");
      }
    }
    class C0 extends C1 {
      public static void main(java.lang.String[] strArr) {
        C0 c = new C0();
        c.foo();
      }
    }

The root cause of this bug lies in the R8 compiler's failure to correctly handle a complex inter-class structure. This structure is formed by a mix of inheritance (C0 extends C1) and interface implementation (C1 implements I). Within this structure, C0 is meant to access foo() from interface I indirectly, through its parent class C1. This creates a clear invocation chain: C0 → C1 → I. However, when generating compatibility code, the R8 compiler failed to respect this chain. It improperly bypassed the intermediary class C1. Instead, it generated invalid code that caused C0 to attempt a direct call to a method on interface I. This attempt to bypass the class hierarchy violates Java's fundamental access control rules. As a result, the program crashes at runtime with an IllegalAccessError.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages