diff --git a/projects/apache-commons-beanutils/Dockerfile b/projects/apache-commons-beanutils/Dockerfile
new file mode 100644
index 000000000..443873c10
--- /dev/null
+++ b/projects/apache-commons-beanutils/Dockerfile
@@ -0,0 +1,36 @@
+# 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 curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+unzip maven.zip -d $SRC/maven && \
+rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+WORKDIR ${SRC}
+#
+# clone repository
+#
+RUN git clone https://github.com/apache/commons-beanutils.git
+COPY *.diff $SRC/
+RUN cd commons-beanutils && tr -d '\015' < $SRC/remove-rat.diff | git apply
+
+
+ADD pom.xml build.sh ${SRC}/
+ADD src/ ${SRC}/src/
+WORKDIR ${SRC}/commons-beanutils
\ No newline at end of file
diff --git a/projects/apache-commons-beanutils/build.sh b/projects/apache-commons-beanutils/build.sh
new file mode 100644
index 000000000..a8e730389
--- /dev/null
+++ b/projects/apache-commons-beanutils/build.sh
@@ -0,0 +1,75 @@
+#!/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.
+#
+################################################################################
+
+MVN_FLAGS="-DskipTests"
+ALL_JARS=""
+
+# install the build servers' jazzer-api into the maven repository
+pushd "/tmp"
+ ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \
+ -DgroupId="com.code-intelligence" \
+ -DartifactId="jazzer-api" \
+ -Dversion="0.12.0" \
+ -Dpackaging=jar
+popd
+
+pushd "${SRC}/commons-beanutils"
+ ${MVN} package ${MVN_FLAGS}
+ ${MVN} install ${MVN_FLAGS}
+ CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+ -Dexpression=project.version -q -DforceStdout)
+popd
+
+pushd ${SRC}
+ ${MVN} package -DbeanutilsVersion="${CURRENT_VERSION}" ${MVN_FLAGS}
+ install -v target/beanutils-fuzzer-${CURRENT_VERSION}.jar ${OUT}/beanutils-fuzzer-${CURRENT_VERSION}.jar
+ ALL_JARS="${ALL_JARS} beanutils-fuzzer-${CURRENT_VERSION}.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
+
+MVN_FUZZERS_PREFIX="src/main/java"
+
+for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do
+ stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|');
+ # the .java was stripped by sed
+ if (echo ${stripped_path} | grep ".java$"); then
+ continue;
+ fi
+
+ fuzzer_basename=$(basename -s .java $fuzzer)
+ fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g');
+
+ # 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_classname} \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/${fuzzer_basename}
+ chmod u+x $OUT/${fuzzer_basename}
+done
diff --git a/projects/apache-commons-beanutils/pom.xml b/projects/apache-commons-beanutils/pom.xml
new file mode 100644
index 000000000..caf9c3061
--- /dev/null
+++ b/projects/apache-commons-beanutils/pom.xml
@@ -0,0 +1,58 @@
+
+ 4.0.0
+
+ ossfuzz
+ beanutils-fuzzer
+ ${beanutilsVersion}
+ jar
+
+
+ 15
+ 15
+ UTF-8
+ ossfuzz.BeanutilsFuzzer
+
+
+
+
+
+ com.code-intelligence
+ jazzer-api
+ 0.12.0
+
+
+ org.apache.commons
+ commons-beanutils2
+ ${beanutilsVersion}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.3.0
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/apache-commons-beanutils/project.yaml b/projects/apache-commons-beanutils/project.yaml
new file mode 100644
index 000000000..0bbcd32a8
--- /dev/null
+++ b/projects/apache-commons-beanutils/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://commons.apache.org/proper/commons-beanutils/"
+language: jvm
+main_repo: "https://github.com/apache/commons-beanutils.git"
+fuzzing_engines:
+ - libfuzzer
+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"
\ No newline at end of file
diff --git a/projects/apache-commons-beanutils/remove-rat.diff b/projects/apache-commons-beanutils/remove-rat.diff
new file mode 100644
index 000000000..cd410aa94
--- /dev/null
+++ b/projects/apache-commons-beanutils/remove-rat.diff
@@ -0,0 +1,11 @@
+--- a/pom.xml
++++ b/pom.xml
+@@ -361,7 +361,7 @@
+
+
+
+- clean apache-rat:check checkstyle:check verify javadoc:javadoc
++ clean checkstyle:check verify javadoc:javadoc
+
+
+ org.apache.felix
diff --git a/projects/apache-commons-beanutils/src/main/java/ossfuzz/BeanutilsFuzzer.java b/projects/apache-commons-beanutils/src/main/java/ossfuzz/BeanutilsFuzzer.java
new file mode 100644
index 000000000..02d3d6bc1
--- /dev/null
+++ b/projects/apache-commons-beanutils/src/main/java/ossfuzz/BeanutilsFuzzer.java
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+package ossfuzz;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.beanutils2.BasicDynaClass;
+import org.apache.commons.beanutils2.DynaBean;
+import org.apache.commons.beanutils2.DynaClass;
+import org.apache.commons.beanutils2.DynaProperty;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
+
+public class BeanutilsFuzzer {
+
+ String m_string;
+ int m_int;
+ int m_int_array[];
+ String m_string_array[];
+ boolean m_bool;
+ double m_double;
+ float m_float;
+ short m_short;
+ long m_long;
+ Map m_map;
+
+ BeanutilsFuzzer(int integer, String string, int[] intArray, boolean bool, double dbl, float flt,
+ Map map,
+ String string_array[], short shrt, long lng) {
+ m_int = integer;
+ m_string = string;
+ m_bool = bool;
+ m_int_array = intArray;
+ m_double = dbl;
+ m_float = flt;
+ m_map = map;
+ m_string_array = string_array;
+ m_short = shrt;
+ m_long = lng;
+ }
+
+ BeanutilsFuzzer(FuzzedDataProvider fuzzedDataProvider) {
+
+ m_int = fuzzedDataProvider.consumeInt();
+ m_int_array = fuzzedIntArray(fuzzedDataProvider);
+ m_bool = fuzzedDataProvider.consumeBoolean();
+ m_double = fuzzedDataProvider.consumeDouble();
+ m_float = fuzzedDataProvider.consumeFloat();
+ m_map = fuzzedMap(fuzzedDataProvider);
+ m_string_array = fuzzedStringArray(fuzzedDataProvider);
+ m_short = fuzzedDataProvider.consumeShort();
+ m_long = fuzzedDataProvider.consumeLong();
+
+ m_string = fuzzedDataProvider.consumeRemainingAsAsciiString();
+ }
+
+ protected DynaClass createDynaClass() {
+
+ final int[] intArray = new int[0];
+ final String[] stringArray = new String[0];
+
+ final DynaClass dynaClass = new BasicDynaClass("TestDynaClass", null,
+ new DynaProperty[] {
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("booleanSecond", Boolean.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intArray", intArray.getClass()),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("mappedProperty", Map.class),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringArray", stringArray.getClass()),
+ new DynaProperty("stringProperty", String.class),
+ });
+ return dynaClass;
+
+ }
+
+ int[] fuzzedIntArray(FuzzedDataProvider fuzzedDataProvider) {
+ int n = fuzzedDataProvider.consumeInt(1, 100);
+ int array[] = new int[n];
+ for (int i = 0; i < n; ++i) {
+ array[i] = fuzzedDataProvider.consumeInt();
+ }
+ return array;
+ }
+
+ String[] fuzzedStringArray(FuzzedDataProvider fuzzedDataProvider) {
+ int n = fuzzedDataProvider.consumeInt(1, 100);
+ String array[] = new String[n];
+ for (int i = 0; i < n; ++i) {
+ array[i] = fuzzedDataProvider.consumeString(16);
+ }
+ return array;
+ }
+
+ Map fuzzedMap(FuzzedDataProvider fuzzedDataProvider) {
+ int n = fuzzedDataProvider.consumeInt(1, 100);
+ Map map = new HashMap();
+
+ for (int i = 0; i < n; i++) {
+ switch (fuzzedDataProvider.consumeInt(0, 7)) {
+ case 0:
+ map.put(fuzzedDataProvider.consumeString(16), new Integer(fuzzedDataProvider.consumeInt()));
+ break;
+ case 1:
+ map.put(fuzzedDataProvider.consumeString(16), new Float(fuzzedDataProvider.consumeFloat()));
+ break;
+ case 2:
+ map.put(fuzzedDataProvider.consumeString(16), new Double(fuzzedDataProvider.consumeDouble()));
+ break;
+ case 3:
+ map.put(fuzzedDataProvider.consumeString(16), new String(fuzzedDataProvider.consumeString(16)));
+ break;
+ case 4:
+ map.put(fuzzedDataProvider.consumeString(16), new Boolean(fuzzedDataProvider.consumeBoolean()));
+ break;
+ case 5:
+ map.put(fuzzedDataProvider.consumeString(16), fuzzedIntArray(fuzzedDataProvider));
+ break;
+ case 6:
+ map.put(fuzzedDataProvider.consumeString(16), fuzzedMap(fuzzedDataProvider));
+ break;
+ }
+
+ }
+
+ return map;
+ }
+
+ void test() throws Exception {
+
+ final DynaClass dynaClass = createDynaClass();
+ DynaBean bean = dynaClass.newInstance();
+
+ bean.set("booleanProperty", new Boolean(m_bool));
+ bean.set("booleanSecond", new Boolean(m_bool));
+
+ if (!bean.get("booleanSecond").equals(new Boolean(m_bool))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("doubleProperty", new Double(m_double));
+ if (!bean.get("doubleProperty").equals(new Double(m_double))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("floatProperty", new Float(m_float));
+ if (!bean.get("floatProperty").equals(new Float(m_float))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("intArray", m_int_array);
+ if (!bean.get("intArray").equals(m_int_array)) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("stringArray", m_string_array);
+ if (!bean.get("stringArray").equals(m_string_array)) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("mappedProperty", m_map);
+ if (!bean.get("mappedProperty").equals(m_map)) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("intProperty", new Integer(m_int));
+ if (!bean.get("intProperty").equals(new Integer(m_int))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("longProperty", new Long(m_long));
+ if (!bean.get("longProperty").equals(new Long(m_long))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+
+ bean.set("shortProperty", new Short(m_short));
+ if (!bean.get("shortProperty").equals(new Short(m_short))) {
+ throw new FuzzerSecurityIssueLow("Data corruption detected");
+ }
+ }
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception {
+ BeanutilsFuzzer testClosure = new BeanutilsFuzzer(fuzzedDataProvider);
+
+ testClosure.test();
+ }
+}
\ No newline at end of file