Skip to content

Commit

Permalink
[CPP/C-frontend] Fix unit test (#1947)
Browse files Browse the repository at this point in the history
* [CPP/C-frontend] Fix unit test

Signed-off-by: Arthur Chan <arthur.chan@adalogics.com>

* Add license

Signed-off-by: Arthur Chan <arthur.chan@adalogics.com>

---------

Signed-off-by: Arthur Chan <arthur.chan@adalogics.com>
  • Loading branch information
arthurscchan authored Jan 10, 2025
1 parent 9d8f4e6 commit 7b73bce
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 38 deletions.
3 changes: 3 additions & 0 deletions src/fuzz_introspector/frontends/frontend_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ def get_reachable_functions(
callsites = func.callsites()
visited_functions.add(function)
for cs, _ in callsites:
if cs in visited_functions:
continue

visited_functions = self.get_reachable_functions(
function=cs, visited_functions=visited_functions)
return visited_functions
Expand Down
3 changes: 3 additions & 0 deletions src/fuzz_introspector/frontends/frontend_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,9 @@ def get_reachable_functions(self,
return visited_functions

for cs, _ in func_node.base_callsites:
if cs in visited_functions:
continue

visited_functions = self.get_reachable_functions(
source_code=source_code,
function=cs,
Expand Down
24 changes: 12 additions & 12 deletions src/fuzz_introspector/frontends/oss_fuzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import argparse
import logging

from typing import Any, Tuple
from typing import Any

from fuzz_introspector.frontends import frontend_c
from fuzz_introspector.frontends import frontend_cpp
Expand Down Expand Up @@ -60,7 +60,7 @@ def process_c_project(target_dir: str,
entrypoint: str,
out: str,
module_only: bool = False,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> frontend_c.Project:
"""Process a project in C language"""
calltrees = []
source_files = {}
Expand Down Expand Up @@ -115,13 +115,13 @@ def process_c_project(target_dir: str,
f.write(calltree)
f.write("====================================")

return calltrees, project
return project


def process_cpp_project(target_dir: str,
entrypoint: str,
out: str,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> frontend_cpp.Project:
"""Process a project in CPP language"""
# Extract c++ source files
logger.info('Going C++ route')
Expand Down Expand Up @@ -160,12 +160,12 @@ def process_cpp_project(target_dir: str,
with open(target, 'w', encoding='utf-8') as f:
f.write(f'Call tree\n{calltree}')

return calltrees, project
return project


def process_go_project(target_dir: str,
out: str,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> frontend_go.Project:
"""Process a project in Go language"""
# Extract go source files
logger.info('Going Go route')
Expand Down Expand Up @@ -197,13 +197,13 @@ def process_go_project(target_dir: str,
with open(target, 'w', encoding='utf-8') as f:
f.write(f'Call tree\n{calltree}')

return calltrees, project
return project


def process_jvm_project(target_dir: str,
entrypoint: str,
out: str,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> frontend_jvm.Project:
"""Process a project in JVM based language"""
# Extract java source files
logger.info('Going JVM route')
Expand Down Expand Up @@ -237,12 +237,12 @@ def process_jvm_project(target_dir: str,
with open(target, 'w', encoding='utf-8') as f:
f.write(f'Call tree\n{calltree}')

return calltrees, project
return project


def process_rust_project(target_dir: str,
out: str,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> frontend_rust.Project:
"""Process a project in Rust based language"""
# Extract rust source files
logger.info('Going Rust route')
Expand Down Expand Up @@ -276,15 +276,15 @@ def process_rust_project(target_dir: str,
with open(target, 'w', encoding='utf-8') as f:
f.write(f'Call tree\n{calltree}')

return calltrees, project
return project


def analyse_folder(language: str = '',
directory: str = '',
entrypoint: str = '',
out='',
module_only=False,
dump_output=True) -> Tuple[list[str], Any]:
dump_output=True) -> Any:
"""Runs a full frontend analysis on a given directory"""

if language == 'c':
Expand Down
15 changes: 15 additions & 0 deletions src/test/data/source-code/cpp/test-project-5/test.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/* Copyright 2025 Fuzz Introspector Authors
*
* 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.
*/

#include "test.hpp"
#include <iostream>

Expand Down
16 changes: 15 additions & 1 deletion src/test/data/source-code/cpp/test-project-5/test.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
// Header File: test.hpp
/* Copyright 2025 Fuzz Introspector Authors
*
* 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.
*/

#ifndef TEST_HPP
#define TEST_HPP

Expand Down
2 changes: 1 addition & 1 deletion src/test/test_frontends_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


def test_simple_sample1():
callsites, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
language='c',
directory='src/test/data/source-code/c/simple-sample-1/',
entrypoint='LLVMFuzzerTestOneInput',
Expand Down
58 changes: 34 additions & 24 deletions src/test/test_frontends_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


def test_tree_sitter_cpp_sample1():
callsites, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
'c++',
'src/test/data/source-code/cpp/test-project-1',
'LLVMFuzzerTestOneInput',
Expand All @@ -27,36 +27,38 @@ def test_tree_sitter_cpp_sample1():
# Project check
assert len(project.get_source_codes_with_harnesses()) == 1

functions_reached = project.get_reachable_functions(
source_code=None,
function='LLVMFuzzerTestOneInput',
visited_functions=set())

# Callsite check
assert len(callsites[0].split('\n')) == 7
assert (' isPositive '
'src/test/data/source-code/cpp/test-project-1/sample.cpp'
in callsites[0])
assert 'isPositive' in functions_reached


def test_tree_sitter_cpp_sample2():
callsites, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
'c++',
'src/test/data/source-code/cpp/test-project-2',
'LLVMFuzzerTestOneInput',
dump_output=False,
)

# Project checkdata/source-code
# Project check
assert len(project.get_source_codes_with_harnesses()) == 1

functions_reached = project.get_reachable_functions(
source_code=None,
function='LLVMFuzzerTestOneInput',
visited_functions=set())

# Callsite check
assert len(callsites[0].split('\n')) == 10
assert (' RecursiveNamespace::fibonacci '
'src/test/data/source-code/cpp/test-project-2/recursive.cpp'
in callsites[0])
assert (' File2Namespace::functionInFile2 '
'src/test/data/source-code/cpp/test-project-2/crossfile.cpp'
in callsites[0])
assert 'RecursiveNamespace::fibonacci' in functions_reached
assert 'File2Namespace::functionInFile2' in functions_reached


def test_tree_sitter_cpp_sample3():
callsites, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
'c++',
'src/test/data/source-code/cpp/test-project-3',
'LLVMFuzzerTestOneInput',
Expand All @@ -66,46 +68,54 @@ def test_tree_sitter_cpp_sample3():
# Project check
assert len(project.get_source_codes_with_harnesses()) == 1

functions_reached = project.get_reachable_functions(
source_code=None,
function='LLVMFuzzerTestOneInput',
visited_functions=set())

# Callsite check
assert len(callsites[0].split('\n')) == 14
assert (' std::reverse '
'src/test/data/source-code/cpp/test-project-3/deep_chain.cpp'
in callsites[0])
assert (' DeepNamespace::level5 '
'src/test/data/source-code/cpp/test-project-3/deep_chain.cpp'
in callsites[0])
assert 'std::reverse' in functions_reached
assert 'DeepNamespace::level5' in functions_reached


def test_tree_sitter_cpp_sample4():
_, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
'c++',
'src/test/data/source-code/cpp/test-project-4',
'LLVMFuzzerTestOneInput',
dump_output=False,
)

# Project check
assert len(project.get_source_codes_with_harnesses()) == 1

functions_reached = project.get_reachable_functions(
source_code=None,
function='LLVMFuzzerTestOneInput',
visited_functions=set())

# Callsite check
assert 'Level1::Level2::Level3::Level4::DeepClass::deepMethod2' in functions_reached
assert 'printf' in functions_reached
assert 'atoi' in functions_reached


def test_tree_sitter_cpp_sample5():
_, project = oss_fuzz.analyse_folder(
project = oss_fuzz.analyse_folder(
'c++',
'src/test/data/source-code/cpp/test-project-5',
'LLVMFuzzerTestOneInput',
dump_output=False,
)

# Project check
assert len(project.get_source_codes_with_harnesses()) == 1

functions_reached = project.get_reachable_functions(
source_code=None,
function='LLVMFuzzerTestOneInput',
visited_functions=set())

# Callsite check
assert 'ClassOne::processInput' in functions_reached
assert 'NamespaceOne::processInput' in functions_reached

0 comments on commit 7b73bce

Please sign in to comment.