diff --git a/projects/groovy/Dockerfile b/projects/groovy/Dockerfile new file mode 100644 index 000000000..4d706eb42 --- /dev/null +++ b/projects/groovy/Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2022 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. +# +################################################################################ + +FROM gcr.io/oss-fuzz-base/base-builder-jvm + +RUN git clone https://github.com/apache/groovy.git + +COPY build.sh $SRC/ +COPY *.java $SRC/ +WORKDIR $SRC/groovy diff --git a/projects/groovy/DurationFuzzer.java b/projects/groovy/DurationFuzzer.java new file mode 100644 index 000000000..1a9593c12 --- /dev/null +++ b/projects/groovy/DurationFuzzer.java @@ -0,0 +1,90 @@ +// Copyright 2022 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. +// +//////////////////////////////////////////////////////////////////////////////// + +import com.code_intelligence.jazzer.api.FuzzedDataProvider; + +import groovy.time.*; + +public class DurationFuzzer { + + int years[] = null; + int months[] = null; + int days[] = null; + int hours[] = null; + int minutes[] = null; + int seconds[] = null; + int millis[] = null; + + public DurationFuzzer(FuzzedDataProvider data) { + years=new int[] { data.consumeInt(), data.consumeInt() }; + months=new int[] { data.consumeInt(), data.consumeInt() }; + days=new int[] { data.consumeInt(), data.consumeInt() }; + hours=new int[] { data.consumeInt(), data.consumeInt() }; + minutes=new int[] { data.consumeInt(), data.consumeInt() }; + seconds=new int[] { data.consumeInt(), data.consumeInt() }; + millis=new int[] { data.consumeInt(), data.consumeInt() }; + } + + void runTest(BaseDuration duration1, BaseDuration duration2) { + duration1.getAgo(); + duration1.compareTo(duration2); + duration1.getHours(); + duration1.getMillis(); + duration1.getMinutes(); + duration1.getMonths(); + duration1.getSeconds(); + duration1.getYears(); + duration1.toString(); + duration1.getFrom(); + duration1.getFrom().getNow(); + duration1.getFrom().getToday(); + duration1.toMilliseconds(); + } + + void runTest(Duration duration1, Duration duration2) { + runTest((BaseDuration)duration1, duration2); + duration1.minus(duration2); + duration1.plus(duration2); + } + void runTest(TimeDuration duration1, TimeDuration duration2) { + runTest((BaseDuration)duration1, duration2); + duration1.minus(duration2); + duration1.plus(duration2); + } + void runTest(DatumDependentDuration duration1, DatumDependentDuration duration2) { + runTest((BaseDuration)duration1, duration2); + duration1.minus(duration2); + duration1.plus(duration2); + } + void runTest(DatumDependentDuration duration1, TimeDatumDependentDuration duration2) { + runTest((BaseDuration)duration1, duration2); + duration1.plus(duration2); + } + + void runTest(FuzzedDataProvider data) { + + runTest(new Duration(days[0], hours[0], minutes[0], seconds[0], millis[0]), new Duration(days[1], hours[1], minutes[1], seconds[1], millis[1])); + runTest(new TimeDuration(days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDuration(days[1], hours[1], minutes[1], seconds[1], millis[1])); + runTest(new DatumDependentDuration(years[0], months[0],days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDuration(days[1], hours[1], minutes[1], seconds[1], millis[1])); + runTest(new DatumDependentDuration(years[0], months[0],days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDatumDependentDuration(years[1], months[1], days[1], hours[1], minutes[1], seconds[1], millis[1])); + + } + + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + DurationFuzzer testClosure = new DurationFuzzer(data); + testClosure.runTest(data); + } +} diff --git a/projects/groovy/build.sh b/projects/groovy/build.sh new file mode 100644 index 000000000..6b49b2555 --- /dev/null +++ b/projects/groovy/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash -eu +# Copyright 2022 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. +# +################################################################################ + + +ALL_JARS="" + +pushd "${SRC}/groovy" + ./gradlew jar + cp -v ./build/libs/groovy-raw-*-SNAPSHOT.jar "$OUT/groovy.jar" + ALL_JARS="${ALL_JARS} groovy.jar" +popd + +# The classpath at build-time includes the project jars in $OUT as well as the +# Jazzer API. +BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH + +# All .jar and .class files lie in the same directory as the fuzzer at runtime. +RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir + +# compile all java files and copy them to $OUT +javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java +cp $SRC/*.class $OUT/ + +for fuzzer in $(find $SRC -name '*Fuzzer.java'); do + fuzzer_basename=$(basename -s .java $fuzzer) + + # Create an execution wrapper that executes Jazzer with the correct arguments. + echo "#!/bin/sh +# LLVMFuzzerTestOneInput for fuzzer detection. +this_dir=\$(dirname \"\$0\") +LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ +\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ +--cp=$RUNTIME_CLASSPATH \ +--target_class=$fuzzer_basename \ +--jvm_args=\"-Xmx2048m\" \ +\$@" > $OUT/$fuzzer_basename + chmod u+x $OUT/$fuzzer_basename +done \ No newline at end of file diff --git a/projects/groovy/project.yaml b/projects/groovy/project.yaml new file mode 100644 index 000000000..16d1acf50 --- /dev/null +++ b/projects/groovy/project.yaml @@ -0,0 +1,14 @@ +fuzzing_engines: +- libfuzzer +homepage: https://groovy-lang.org/ +language: jvm +main_repo: https://github.com/apache/groovy.git +sanitizers: +- address +vendor_ccs: + - "wagner@code-intelligence.com" + - "yakdan@code-intelligence.com" + - "glendowne@code-intelligence.com" + - "patrice.salathe@code-intelligence.com" + - "hlin@code-intelligence.com" + - "schaich@code-intelligence.com"