diff --git a/projects/jsonp-api/CreateJsonFuzzer.java b/projects/jsonp-api/CreateJsonFuzzer.java new file mode 100644 index 000000000000..c81d71f9bc13 --- /dev/null +++ b/projects/jsonp-api/CreateJsonFuzzer.java @@ -0,0 +1,64 @@ +// Copyright 2023 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 com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; +import ee.jakarta.tck.jsonp.common.JSONP_Util; +import jakarta.json.*; +import jakarta.json.stream.JsonParsingException; +import java.io.PrintStream; +import java.io.OutputStream; + +public class CreateJsonFuzzer { + private static final PrintStream noopStream = new PrintStream(new OutputStream() { + @Override + public void write(int b) {} + }); + + public static void fuzzerInitialize() { + System.setErr(noopStream); + System.setOut(noopStream); + } + + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + try { + testJsonCreators(data); + JsonValue.ValueType.valueOf(data.consumeString(100)); + } catch (IllegalArgumentException | JsonParsingException e) {} + } + + public static void testJsonCreators(FuzzedDataProvider data) { + JsonArray jsonArray = JSONP_Util.createJsonArrayFromString(data.consumeString(200)); + JSONP_Util.toStringJsonArray(jsonArray); + + JsonObject jsonObject = JSONP_Util.createJsonObjectFromString(data.consumeString(200)); + JSONP_Util.toStringJsonObject(jsonObject); + + String inStr = data.consumeAsciiString(200); + JsonString jsonString = JSONP_Util.createJsonString(inStr); + String outString = JSONP_Util.toStringJsonString(jsonString); + String intJsonStr = "\"" + inStr + "\""; + if (!intJsonStr.equals(outString)) { + throw new FuzzerSecurityIssueLow("JsonString: " + intJsonStr + " Expected. Got " + outString); + } + + int inNumber = data.consumeInt(); + JsonNumber jsonNumber = JSONP_Util.createJsonNumber(inNumber); + String outNumber = JSONP_Util.toStringJsonNumber(jsonNumber); + if (!Integer.toString(inNumber).equals(outNumber)) { + throw new FuzzerSecurityIssueLow("JsonNumber: " + inNumber + " Expected. Got " + outNumber); + } + } +} diff --git a/projects/jsonp-api/Dockerfile b/projects/jsonp-api/Dockerfile new file mode 100644 index 000000000000..107f63510d60 --- /dev/null +++ b/projects/jsonp-api/Dockerfile @@ -0,0 +1,28 @@ +# Copyright 2023 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 --depth 1 https://github.com/jakartaee/jsonp-api $SRC/jsonp-api + +RUN curl -L https://downloads.apache.org/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ + unzip maven.zip -d $SRC/maven && \ + rm -rf maven.zip +ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn + +COPY build.sh $SRC/ +COPY *Fuzzer.java $SRC/ +WORKDIR $SRC/jsonp-api \ No newline at end of file diff --git a/projects/jsonp-api/GeneratorFuzzer.java b/projects/jsonp-api/GeneratorFuzzer.java new file mode 100644 index 000000000000..84925bbc8e04 --- /dev/null +++ b/projects/jsonp-api/GeneratorFuzzer.java @@ -0,0 +1,67 @@ +// Copyright 2023 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 com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; +import ee.jakarta.tck.jsonp.common.JSONP_Util; +import jakarta.json.*; +import jakarta.json.stream.JsonGenerator; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; + +public class GeneratorFuzzer { + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json.createGenerator(baos).writeStartObject(); + + try { + for (int i = 0; i < data.consumeInt(0, 10); i++) { + if (data.consumeBoolean()) { + generator.writeStartObject(data.consumeString(20)); + } else { + generator.writeStartArray(data.consumeString(20)); + } + + for (int j = 0; j < data.consumeInt(0, 20); j++) { + int writeChoice = data.consumeInt(0, 3); + switch (writeChoice) { + case 0: + generator.write(data.consumeString(50), data.consumeInt()); + break; + case 1: + generator.write(data.consumeString(50), data.consumeString(50)); + break; + case 2: + generator.write(data.consumeString(50), data.consumeBoolean()); + break; + case 3: + generator.write(JSONP_Util.createJsonString(data.consumeString(50))); + break; + } + } + generator.writeEnd(); + } + + generator.writeEnd(); + generator.close(); + baos.close(); + + JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + + } catch (JsonException | IOException | IllegalArgumentException e) {} + } +} diff --git a/projects/jsonp-api/build.sh b/projects/jsonp-api/build.sh new file mode 100755 index 000000000000..c43c3513584b --- /dev/null +++ b/projects/jsonp-api/build.sh @@ -0,0 +1,65 @@ +#!/bin/bash -eu +# Copyright 2023 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. +# +################################################################################ + +CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ +-Dexpression=project.version -q -DforceStdout) + +cd tck +$MVN -U -C clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true +cp tck-common/target/jakarta*.jar $OUT/ +cp tck-tests/target/jakarta*.jar $OUT/ +cd .. +cd api +$MVN -U -C clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true +cp target/jakarta*.jar $OUT/ +cd .. + +# parsson dependencies need to be downloaded manually +$MVN dependency:get -Dartifact=org.eclipse.parsson:parsson:1.1.1 +cp ~/.m2/repository/org/eclipse/parsson/parsson/1.1.1/*.jar $OUT/ + +ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") + +# 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 + +for fuzzer in $(find $SRC -name '*Fuzzer.java'); do + fuzzer_basename=$(basename -s .java $fuzzer) + javac -cp $BUILD_CLASSPATH $fuzzer + mv $SRC/*.class $OUT/ + + # Create an execution wrapper that executes Jazzer with the correct arguments. + echo "#!/bin/bash +# LLVMFuzzerTestOneInput for fuzzer detection. +this_dir=\$(dirname \"\$0\") +if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then + mem_settings='-Xmx1900m:-Xss900k' +else + mem_settings='-Xmx2048m:-Xss1024k' +fi +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=\"\$mem_settings\" \ +\$@" > $OUT/$fuzzer_basename + chmod u+x $OUT/$fuzzer_basename +done \ No newline at end of file diff --git a/projects/jsonp-api/project.yaml b/projects/jsonp-api/project.yaml new file mode 100644 index 000000000000..35a9395acaf4 --- /dev/null +++ b/projects/jsonp-api/project.yaml @@ -0,0 +1,9 @@ +homepage: "https://github.com/jakartaee/jsonp-api" +language: jvm +fuzzing_engines: + - libfuzzer +main_repo: "https://github.com/jakartaee/jsonp-api" +sanitizers: + - address +vendor_ccs: + - "bug-disclosure@code-intelligence.com" \ No newline at end of file