Skip to content

Commit

Permalink
Add more test projects and fix more bugs
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Chan <arthur.chan@adalogics.com>
  • Loading branch information
arthurscchan committed Jan 10, 2025
1 parent a818190 commit ff7f8a7
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 26 deletions.
83 changes: 57 additions & 26 deletions src/fuzz_introspector/frontends/frontend_jvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,32 +243,40 @@ class JavaMethod():
def __init__(self,
root: Node,
class_interface: 'JavaClassInterface',
is_constructor: bool = False):
is_constructor: bool = False,
is_default_constructor: bool = False):
self.root = root
self.class_interface = class_interface
self.tree_sitter_lang = self.class_interface.tree_sitter_lang
self.parent_source: Optional[
SourceCodeFile] = self.class_interface.parent_source
self.is_constructor = is_constructor
self.is_default_constructor = is_default_constructor
self.name: str = ''

# Store method line information
self.start_line = self.root.start_point.row + 1
self.end_line = self.root.end_point.row + 1
if self.is_default_constructor:
self.start_line = -1
self.end_line = -1
self.name = '<init>'
self.public = True
else:
self.start_line = self.root.start_point.row + 1
self.end_line = self.root.end_point.row + 1
self.name = ''
self.public = False

# Other properties
self.name: str = ''
self.complexity = 0
self.icount = 0
self.arg_names: list[str] = []
self.arg_types: list[str] = []
self.exceptions: list[str] = []
self.return_type = ''
self.sig = ''
self.function_uses = 0
self.function_depth = 0
self.base_callsites: list[tuple[str, int]] = []
self.detailed_callsites: list[dict[str, str]] = []
self.public = False
self.concrete = True
self.static = False
self.is_entry_method = False
Expand All @@ -277,11 +285,12 @@ def __init__(self,
self.stmts: list[Node] = []
self.var_map: dict[str, str] = {}

# Process method declaration
self._process_declaration()
if not self.is_default_constructor:
# Process method declaration
self._process_declaration()

# Process statements
self._process_statements()
# Process statements
self._process_statements()

def post_process_full_qualified_name(self):
"""Post process the full qualified name for types."""
Expand Down Expand Up @@ -374,7 +383,6 @@ def _process_statements(self):
for stmt in self.stmts:
self._process_complexity(stmt)
self._process_icount(stmt)
self._process_variable_declaration(stmt)

def _process_complexity(self, stmt: Node):
"""Gets complexity measure based on counting branch nodes in a
Expand Down Expand Up @@ -443,21 +451,6 @@ def _traverse_node_instr_count(node: Node) -> int:

self.icount += _traverse_node_instr_count(stmt)

def _process_variable_declaration(self, stmt: Node):
"""Process the local variable declaration."""
variable_type = None
variable_name = None

if stmt.type == 'local_variable_declaration':
variable_type = stmt.child_by_field_name('type').text.decode()
for vars in stmt.children:
if vars.type == 'variable_declarator':
variable_name = vars.child_by_field_name(
'name').text.decode()

if variable_type and variable_name:
self.var_map[variable_name] = variable_type

def _process_invoke_object(
self, stmt: Node, classes: dict[str, 'JavaClassInterface']
) -> tuple[str, list[tuple[str, int, int]]]:
Expand Down Expand Up @@ -752,6 +745,9 @@ def _process_callsites(
type = ''
callsites = []

if not stmt:
return type, callsites

if stmt.type == 'method_invocation':
type, invoke_callsites = self._process_invoke(stmt, classes)
callsites.extend(invoke_callsites)
Expand All @@ -769,6 +765,24 @@ def _process_callsites(
type, invoke_callsites = self._process_callsites(right, classes)
self.var_map[var_name] = type
callsites.extend(invoke_callsites)
elif stmt.type.endswith('local_variable_declarattion'):
for vars in stmt.children:
if vars.type == 'variable_declarator':
var_name = vars.child_by_field_name('name').text.decode()
value_node = vars.child_by_field_name('value')

type, invoke_callsites = self._process_callsites(
value_node, classes)
self.var_map[var_name] = type
callsites.extend(invoke_callsites)
elif stmt.type.endswith('variable_declarator'):
var_name = stmt.child_by_field_name('name').text.decode()
value_node = stmt.child_by_field_name('value')

type, invoke_callsites = self._process_callsites(
value_node, classes)
self.var_map[var_name] = type
callsites.extend(invoke_callsites)
else:
for child in stmt.children:
callsites.extend(self._process_callsites(child, classes)[1])
Expand All @@ -782,6 +796,9 @@ def extract_callsites(self, classes: dict[str, 'JavaClassInterface']):
callsites = []
for stmt in self.stmts:
callsites.extend(self._process_callsites(stmt, classes)[1])
if self.is_constructor:
for stmt in self.class_interface.constructor_callsites:
callsites.extend(self._process_callsites(stmt, classes)[1])
callsites = sorted(set(callsites), key=lambda x: x[1])
self.base_callsites = [(x[0], x[2]) for x in callsites]

Expand Down Expand Up @@ -819,13 +836,18 @@ def __init__(self,
self.class_fields: dict[str, str] = {}
self.super_class = 'Object'
self.super_interfaces: list[str] = []
self.constructor_callsites: list[Node] = []

# Process the class/interface tree
inner_class_nodes = self._process_node()

# Process inner classes
self._process_inner_classes(inner_class_nodes)

# Add in default constructor if no deinition of constructors
if not self._has_constructor_defined():
self.methods.append(JavaMethod(self.root, self, True, True))

def add_package_to_class_name(self, name: str) -> Optional[str]:
"""Helper for finding a specific class name."""
if self.name == f'{self.package}.{name.rsplit(".")[-1]}':
Expand Down Expand Up @@ -918,6 +940,7 @@ def _process_node(self) -> list[Node]:
for fields in body.children:
# Process field_name
if fields.type == 'variable_declarator':
self.constructor_callsites.append(fields)
field_name = fields.child_by_field_name(
'name').text.decode()

Expand All @@ -937,6 +960,14 @@ def _process_inner_classes(self, inner_class_nodes: list[Node]):
JavaClassInterface(node, self.tree_sitter_lang,
self.parent_source, self))

def _has_constructor_defined(self) -> bool:
"""Helper method to determine if any constructor is defined."""
for method in self.methods:
if method.is_constructor:
return True

return False

def get_all_methods(self) -> list[JavaMethod]:
all_methods = self.methods
for inner_class in self.inner_classes:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package crosspackage;

import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import crosspackage.helper.HelperClass;

public class Fuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
HelperClass helper = new HelperClass();
helper.helperMethod();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package crosspackage.helper;

public class HelperClass {
public void helperMethod() {
System.out.println("Helper Method Called from Another Package");
}

public void unreachableHelperMethod() {
System.out.println("Unreachable Helper Method");
}
}
43 changes: 43 additions & 0 deletions src/test/data/source-code/jvm/test-project-5/complex/Fuzzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package complex;

import com.code_intelligence.jazzer.api.FuzzedDataProvider;

class A {
B b = new B();

void callB() {
b.callC();
}

void unreachableAMethod() {
System.out.println("Unreachable Method in A");
}
}

class B {
C c = new C();

void callC() {
c.finalMethod();
}

void unreachableBMethod() {
System.out.println("Unreachable Method in B");
}
}

class C {
void finalMethod() {
System.out.println("Final Method in Chain Called");
}

void unreachableCMethod() {
System.out.println("Unreachable Method in C");
}
}

public class Fuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
A a = new A();
a.callB();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package inheritance;

import com.code_intelligence.jazzer.api.FuzzedDataProvider;

class SuperClass {
void superMethod() {
System.out.println("SuperClass Method Called");
recursiveHelper(2);
}

void recursiveHelper(int n) {
if (n > 0) {
System.out.println("Superclass Recursion: " + n);
recursiveHelper(n - 1);
}
}

void unreachableSuperMethod() {
System.out.println("Unreachable Method in SuperClass");
}
}

class SubClass extends SuperClass {
@Override
void superMethod() {
System.out.println("SubClass Method Overriding SuperClass");
super.superMethod();
}

void unreachableSubMethod() {
System.out.println("Unreachable Method in SubClass");
}
}

public class Fuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
SuperClass obj;
if ("subclass".equals(data.consumeString(10))) {
obj = new SubClass();
} else {
obj = new SuperClass();
}
obj.superMethod();
}
}
49 changes: 49 additions & 0 deletions src/test/data/source-code/jvm/test-project-7/combined/Fuzzer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package combined;

import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import combined.helper.HelperClass;

abstract class AbstractBase {
abstract void abstractMethod();

void unreachableAbstractBaseMethod() {
System.out.println("Unreachable Method in AbstractBase");
}
}

class ConcreteClass extends AbstractBase {
@Override
void abstractMethod() {
System.out.println("ConcreteClass Implementation of Abstract Method");
}

void chainMethod() {
System.out.println("Chain Method Called");
NestedClass.InnerClass ic = new NestedClass.InnerClass();
ic.innerMethod();
}

void unreachableConcreteMethod() {
System.out.println("Unreachable Method in ConcreteClass");
}
}

class NestedClass {
static class InnerClass {
void innerMethod() {
System.out.println("Inner Class Method in Combined Project");
}

void unreachableInnerClassMethod() {
System.out.println("Unreachable Method in InnerClass");
}
}
}

public class Fuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
AbstractBase base = new ConcreteClass();
((ConcreteClass) base).chainMethod();
base.abstractMethod();
}
}
Loading

0 comments on commit ff7f8a7

Please sign in to comment.