Skip to content

Commit ff7f8a7

Browse files
committed
Add more test projects and fix more bugs
Signed-off-by: Arthur Chan <[email protected]>
1 parent a818190 commit ff7f8a7

File tree

7 files changed

+293
-26
lines changed

7 files changed

+293
-26
lines changed

src/fuzz_introspector/frontends/frontend_jvm.py

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -243,32 +243,40 @@ class JavaMethod():
243243
def __init__(self,
244244
root: Node,
245245
class_interface: 'JavaClassInterface',
246-
is_constructor: bool = False):
246+
is_constructor: bool = False,
247+
is_default_constructor: bool = False):
247248
self.root = root
248249
self.class_interface = class_interface
249250
self.tree_sitter_lang = self.class_interface.tree_sitter_lang
250251
self.parent_source: Optional[
251252
SourceCodeFile] = self.class_interface.parent_source
252253
self.is_constructor = is_constructor
254+
self.is_default_constructor = is_default_constructor
255+
self.name: str = ''
253256

254257
# Store method line information
255-
self.start_line = self.root.start_point.row + 1
256-
self.end_line = self.root.end_point.row + 1
258+
if self.is_default_constructor:
259+
self.start_line = -1
260+
self.end_line = -1
261+
self.name = '<init>'
262+
self.public = True
263+
else:
264+
self.start_line = self.root.start_point.row + 1
265+
self.end_line = self.root.end_point.row + 1
266+
self.name = ''
267+
self.public = False
257268

258269
# Other properties
259-
self.name: str = ''
260270
self.complexity = 0
261271
self.icount = 0
262272
self.arg_names: list[str] = []
263273
self.arg_types: list[str] = []
264274
self.exceptions: list[str] = []
265275
self.return_type = ''
266-
self.sig = ''
267276
self.function_uses = 0
268277
self.function_depth = 0
269278
self.base_callsites: list[tuple[str, int]] = []
270279
self.detailed_callsites: list[dict[str, str]] = []
271-
self.public = False
272280
self.concrete = True
273281
self.static = False
274282
self.is_entry_method = False
@@ -277,11 +285,12 @@ def __init__(self,
277285
self.stmts: list[Node] = []
278286
self.var_map: dict[str, str] = {}
279287

280-
# Process method declaration
281-
self._process_declaration()
288+
if not self.is_default_constructor:
289+
# Process method declaration
290+
self._process_declaration()
282291

283-
# Process statements
284-
self._process_statements()
292+
# Process statements
293+
self._process_statements()
285294

286295
def post_process_full_qualified_name(self):
287296
"""Post process the full qualified name for types."""
@@ -374,7 +383,6 @@ def _process_statements(self):
374383
for stmt in self.stmts:
375384
self._process_complexity(stmt)
376385
self._process_icount(stmt)
377-
self._process_variable_declaration(stmt)
378386

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

444452
self.icount += _traverse_node_instr_count(stmt)
445453

446-
def _process_variable_declaration(self, stmt: Node):
447-
"""Process the local variable declaration."""
448-
variable_type = None
449-
variable_name = None
450-
451-
if stmt.type == 'local_variable_declaration':
452-
variable_type = stmt.child_by_field_name('type').text.decode()
453-
for vars in stmt.children:
454-
if vars.type == 'variable_declarator':
455-
variable_name = vars.child_by_field_name(
456-
'name').text.decode()
457-
458-
if variable_type and variable_name:
459-
self.var_map[variable_name] = variable_type
460-
461454
def _process_invoke_object(
462455
self, stmt: Node, classes: dict[str, 'JavaClassInterface']
463456
) -> tuple[str, list[tuple[str, int, int]]]:
@@ -752,6 +745,9 @@ def _process_callsites(
752745
type = ''
753746
callsites = []
754747

748+
if not stmt:
749+
return type, callsites
750+
755751
if stmt.type == 'method_invocation':
756752
type, invoke_callsites = self._process_invoke(stmt, classes)
757753
callsites.extend(invoke_callsites)
@@ -769,6 +765,24 @@ def _process_callsites(
769765
type, invoke_callsites = self._process_callsites(right, classes)
770766
self.var_map[var_name] = type
771767
callsites.extend(invoke_callsites)
768+
elif stmt.type.endswith('local_variable_declarattion'):
769+
for vars in stmt.children:
770+
if vars.type == 'variable_declarator':
771+
var_name = vars.child_by_field_name('name').text.decode()
772+
value_node = vars.child_by_field_name('value')
773+
774+
type, invoke_callsites = self._process_callsites(
775+
value_node, classes)
776+
self.var_map[var_name] = type
777+
callsites.extend(invoke_callsites)
778+
elif stmt.type.endswith('variable_declarator'):
779+
var_name = stmt.child_by_field_name('name').text.decode()
780+
value_node = stmt.child_by_field_name('value')
781+
782+
type, invoke_callsites = self._process_callsites(
783+
value_node, classes)
784+
self.var_map[var_name] = type
785+
callsites.extend(invoke_callsites)
772786
else:
773787
for child in stmt.children:
774788
callsites.extend(self._process_callsites(child, classes)[1])
@@ -782,6 +796,9 @@ def extract_callsites(self, classes: dict[str, 'JavaClassInterface']):
782796
callsites = []
783797
for stmt in self.stmts:
784798
callsites.extend(self._process_callsites(stmt, classes)[1])
799+
if self.is_constructor:
800+
for stmt in self.class_interface.constructor_callsites:
801+
callsites.extend(self._process_callsites(stmt, classes)[1])
785802
callsites = sorted(set(callsites), key=lambda x: x[1])
786803
self.base_callsites = [(x[0], x[2]) for x in callsites]
787804

@@ -819,13 +836,18 @@ def __init__(self,
819836
self.class_fields: dict[str, str] = {}
820837
self.super_class = 'Object'
821838
self.super_interfaces: list[str] = []
839+
self.constructor_callsites: list[Node] = []
822840

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

826844
# Process inner classes
827845
self._process_inner_classes(inner_class_nodes)
828846

847+
# Add in default constructor if no deinition of constructors
848+
if not self._has_constructor_defined():
849+
self.methods.append(JavaMethod(self.root, self, True, True))
850+
829851
def add_package_to_class_name(self, name: str) -> Optional[str]:
830852
"""Helper for finding a specific class name."""
831853
if self.name == f'{self.package}.{name.rsplit(".")[-1]}':
@@ -918,6 +940,7 @@ def _process_node(self) -> list[Node]:
918940
for fields in body.children:
919941
# Process field_name
920942
if fields.type == 'variable_declarator':
943+
self.constructor_callsites.append(fields)
921944
field_name = fields.child_by_field_name(
922945
'name').text.decode()
923946

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

963+
def _has_constructor_defined(self) -> bool:
964+
"""Helper method to determine if any constructor is defined."""
965+
for method in self.methods:
966+
if method.is_constructor:
967+
return True
968+
969+
return False
970+
940971
def get_all_methods(self) -> list[JavaMethod]:
941972
all_methods = self.methods
942973
for inner_class in self.inner_classes:
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
////////////////////////////////////////////////////////////////////////////////
16+
package crosspackage;
17+
18+
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
19+
import crosspackage.helper.HelperClass;
20+
21+
public class Fuzzer {
22+
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
23+
HelperClass helper = new HelperClass();
24+
helper.helperMethod();
25+
}
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
////////////////////////////////////////////////////////////////////////////////
16+
17+
package crosspackage.helper;
18+
19+
public class HelperClass {
20+
public void helperMethod() {
21+
System.out.println("Helper Method Called from Another Package");
22+
}
23+
24+
public void unreachableHelperMethod() {
25+
System.out.println("Unreachable Helper Method");
26+
}
27+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package complex;
2+
3+
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
4+
5+
class A {
6+
B b = new B();
7+
8+
void callB() {
9+
b.callC();
10+
}
11+
12+
void unreachableAMethod() {
13+
System.out.println("Unreachable Method in A");
14+
}
15+
}
16+
17+
class B {
18+
C c = new C();
19+
20+
void callC() {
21+
c.finalMethod();
22+
}
23+
24+
void unreachableBMethod() {
25+
System.out.println("Unreachable Method in B");
26+
}
27+
}
28+
29+
class C {
30+
void finalMethod() {
31+
System.out.println("Final Method in Chain Called");
32+
}
33+
34+
void unreachableCMethod() {
35+
System.out.println("Unreachable Method in C");
36+
}
37+
}
38+
39+
public class Fuzzer {
40+
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
41+
A a = new A();
42+
a.callB();
43+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
////////////////////////////////////////////////////////////////////////////////
16+
17+
package inheritance;
18+
19+
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
20+
21+
class SuperClass {
22+
void superMethod() {
23+
System.out.println("SuperClass Method Called");
24+
recursiveHelper(2);
25+
}
26+
27+
void recursiveHelper(int n) {
28+
if (n > 0) {
29+
System.out.println("Superclass Recursion: " + n);
30+
recursiveHelper(n - 1);
31+
}
32+
}
33+
34+
void unreachableSuperMethod() {
35+
System.out.println("Unreachable Method in SuperClass");
36+
}
37+
}
38+
39+
class SubClass extends SuperClass {
40+
@Override
41+
void superMethod() {
42+
System.out.println("SubClass Method Overriding SuperClass");
43+
super.superMethod();
44+
}
45+
46+
void unreachableSubMethod() {
47+
System.out.println("Unreachable Method in SubClass");
48+
}
49+
}
50+
51+
public class Fuzzer {
52+
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
53+
SuperClass obj;
54+
if ("subclass".equals(data.consumeString(10))) {
55+
obj = new SubClass();
56+
} else {
57+
obj = new SuperClass();
58+
}
59+
obj.superMethod();
60+
}
61+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package combined;
2+
3+
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
4+
import combined.helper.HelperClass;
5+
6+
abstract class AbstractBase {
7+
abstract void abstractMethod();
8+
9+
void unreachableAbstractBaseMethod() {
10+
System.out.println("Unreachable Method in AbstractBase");
11+
}
12+
}
13+
14+
class ConcreteClass extends AbstractBase {
15+
@Override
16+
void abstractMethod() {
17+
System.out.println("ConcreteClass Implementation of Abstract Method");
18+
}
19+
20+
void chainMethod() {
21+
System.out.println("Chain Method Called");
22+
NestedClass.InnerClass ic = new NestedClass.InnerClass();
23+
ic.innerMethod();
24+
}
25+
26+
void unreachableConcreteMethod() {
27+
System.out.println("Unreachable Method in ConcreteClass");
28+
}
29+
}
30+
31+
class NestedClass {
32+
static class InnerClass {
33+
void innerMethod() {
34+
System.out.println("Inner Class Method in Combined Project");
35+
}
36+
37+
void unreachableInnerClassMethod() {
38+
System.out.println("Unreachable Method in InnerClass");
39+
}
40+
}
41+
}
42+
43+
public class Fuzzer {
44+
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
45+
AbstractBase base = new ConcreteClass();
46+
((ConcreteClass) base).chainMethod();
47+
base.abstractMethod();
48+
}
49+
}

0 commit comments

Comments
 (0)