Skip to content

Commit

Permalink
infra: Fix jvm coverage report (#12694)
Browse files Browse the repository at this point in the history
The current JVM coverage calculation includes all class files and JAR
files in $OUT. If the project has copied necessary dependency JAR files
to $OUT for fuzzing purposes, those classes will also be included in the
JaCoCo coverage report, adding noise. This PR addresses that issue by
only copying class files located in the $OUT/$SRC directory, which are
lively compiled from the project source code, ensuring that only project
classes are used by jacoco-cli to generate the coverage report. As all
JVM languages compile to class files, this approach should work for all
JVM languages supported by OSS-Fuzz in general.

---------

Signed-off-by: Arthur Chan <[email protected]>
Co-authored-by: DavidKorczynski <[email protected]>
  • Loading branch information
arthurscchan and DavidKorczynski authored Dec 4, 2024
1 parent 3d38acd commit 8bc2e0b
Showing 1 changed file with 14 additions and 33 deletions.
47 changes: 14 additions & 33 deletions infra/base-images/base-runner/coverage
Original file line number Diff line number Diff line change
Expand Up @@ -434,46 +434,27 @@ elif [[ $FUZZING_LANGUAGE == "jvm" ]]; then
java -jar /opt/jacoco-cli.jar merge $DUMPS_DIR/*.exec \
--destfile $jacoco_merged_exec

# Merge .class files from the individual targets.
# Prepare classes directory for jacoco process
classes_dir=$DUMPS_DIR/classes
mkdir $classes_dir
for fuzz_target in $FUZZ_TARGETS; do
# Continue if not a fuzz target.
if [[ $FUZZING_ENGINE != "none" ]]; then
grep "LLVMFuzzerTestOneInput" $fuzz_target > /dev/null 2>&1 || continue

# Only copy class files found in $OUT/$SRC to ensure they are
# lively compiled from the project, avoiding inclusion of
# dependency classes. This also includes the fuzzer classes.
find "$OUT/$SRC" -type f -name "*.class" | while read -r class_file; do
# Skip module-info.class
if [[ "$(basename "$class_file")" == "module-info.class" ]]; then
continue
fi
cp -r $DUMPS_DIR/${fuzz_target}_classes/* $classes_dir/
done

# Dump classes in jar file to dump directory. This action includes all
# the classes of the project that are not executed by the fuzzers to
# the dump directory. Duplicate classes in the dump directory will be
# overwritten. We need to do this to include all possible classes in
# the coverage report and avoid duplicate classes from different jar
# files which jacoco fails to handle.
for jar_file in $(ls $OUT/*.jar)
do
if [[ $jar_file != $OUT/jazzer* ]]
then
tempdir=$(mktemp -d)
cd $tempdir && jar xvf $jar_file && cd -
cp -r $tempdir/* $classes_dir/
rm -r $tempdir
# Use javap to extract the fully qualified name of the class and copy it to $classes_dir
fqn=$(javap -verbose "$class_file" 2>/dev/null | grep "this_class:" | grep -oP '(?<=// ).*')
if [ -n "$fqn" ]; then
mkdir -p $classes_dir/$(dirname $fqn)
cp $class_file $classes_dir/$fqn.class
fi
done

# Clean up files that can create duplicate class names which breaks Jacoco.
# Remove META-INF folder because some jar may store duplications of the same
# class file in the META-INF for other java versions.
find $classes_dir -name "META-INF" | xargs rm -rf
# Remove all files that are not a java class because some jar may contain
# Kotlin class which has the same name as a java class and Jacoco fail to
# distinguish them.
find $classes_dir -type f -not -name "*.class" | xargs rm -f
# Remove all class files which have a dot in their file name which are normally
# used to name a duplication of the legitimate class file.
find $classes_dir/*/ -type f -name "*.*.class" | xargs rm -f

# Heuristically determine source directories based on Maven structure.
# Always include the $SRC root as it likely contains the fuzzer sources.
sourcefiles_args=(--sourcefiles $OUT/$SRC)
Expand Down

0 comments on commit 8bc2e0b

Please sign in to comment.