From 45118f438347dc700bacd0b070083f428da33e8e Mon Sep 17 00:00:00 2001 From: "Patrice.S" Date: Mon, 3 Oct 2022 17:44:17 +0200 Subject: [PATCH] spring-webflux: initial integration (#8642) --- projects/spring-framework/build.sh | 44 +++-- .../spring-webflux/BindStatusFuzzer.java | 173 ++++++++++++++++++ 2 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 projects/spring-framework/spring-webflux/BindStatusFuzzer.java diff --git a/projects/spring-framework/build.sh b/projects/spring-framework/build.sh index 0bff03a3e..5a786dbf3 100755 --- a/projects/spring-framework/build.sh +++ b/projects/spring-framework/build.sh @@ -21,38 +21,43 @@ export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" -CURRENT_VERSION=$(./gradlew properties --console=plain | sed -nr "s/^version:\ (.*)/\1/p") - -ALL_JARS=""; +export CURRENT_VERSION=$(./gradlew properties --console=plain | sed -nr "s/^version:\ (.*)/\1/p") function install_shadowJar { - ./gradlew shadowJar --build-file spring-$1/spring-$1.gradle -x javadoc -x test - install -v "spring-$1/build/libs/spring-$1-${CURRENT_VERSION}-all.jar" "$OUT/spring-$1.jar"; - ALL_JARS="${ALL_JARS} spring-$1.jar"; + if grep -q shadow $1/$1.gradle; then + ./gradlew shadowJar --build-file $1/$1.gradle -x javadoc -x test + install -v "$1/build/libs/$1-$CURRENT_VERSION-all.jar" "$OUT/$1.jar"; + else + ./gradlew build -x javadoc -x test + install -v "$1/build/libs/$1-$CURRENT_VERSION.jar" "$OUT/$1.jar"; + fi } -install_shadowJar context; -install_shadowJar core; -install_shadowJar jdbc; -install_shadowJar orm; -install_shadowJar web; -install_shadowJar webmvc; -install_shadowJar test; -install_shadowJar tx; -install_shadowJar messaging; -install_shadowJar jms; +install_shadowJar spring-context; +install_shadowJar spring-core; +install_shadowJar spring-jdbc; +install_shadowJar spring-orm; +install_shadowJar spring-web; +install_shadowJar spring-webmvc; +install_shadowJar spring-test; +install_shadowJar spring-tx; +install_shadowJar spring-messaging; +install_shadowJar spring-jms; +install_shadowJar spring-webflux + +ALL_JARS=$(find $OUT -name "spring*.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:$SRC +export BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH:$SRC # 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 +export RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir function create_fuzz_targets() { mkdir -p $SRC/$1 mkdir -p $OUT/$1 - javac -cp $BUILD_CLASSPATH $SRC/$1/*.java --release 17 + javac -cp $BUILD_CLASSPATH --release 17 $(find $SRC/$1/ -name "*.java" -print) for fuzzer in $SRC/$1/*Fuzzer.java; do fuzzer_basename=$(basename -s .java $fuzzer) @@ -84,5 +89,6 @@ create_fuzz_targets spring-web create_fuzz_targets spring-jdbc create_fuzz_targets spring-messaging create_fuzz_targets spring-jms +create_fuzz_targets spring-webflux cp $SRC/spring-jdbc/*.xml $OUT/spring-jdbc/ diff --git a/projects/spring-framework/spring-webflux/BindStatusFuzzer.java b/projects/spring-framework/spring-webflux/BindStatusFuzzer.java new file mode 100644 index 000000000..e401192dd --- /dev/null +++ b/projects/spring-framework/spring-webflux/BindStatusFuzzer.java @@ -0,0 +1,173 @@ +// 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 org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.springframework.context.ApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.NoSuchMessageException; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.context.i18n.SimpleLocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.result.view.BindStatus; +import org.springframework.web.reactive.result.view.RequestContext; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import org.springframework.beans.NotReadablePropertyException; +import java.security.Principal; +import java.time.Instant; +import java.util.*; +import java.util.function.Function; +import reactor.core.publisher.Mono; +import org.springframework.beans.InvalidPropertyException; + +public class BindStatusFuzzer { + public static void fuzzerTestOneInput(FuzzedDataProvider data) { + MockHttpServletRequest request = new MockHttpServletRequest("", ""); + Map objectMap = new HashMap(); + + for (int i = 0; i < data.consumeInt(0, 200); i++) { + String name = data.consumeString(50); + switch (data.consumeInt(0, 3)) { + case 0 -> objectMap.put(name, data.consumeString(50)); + case 1 -> objectMap.put(name, data.consumeInt()); + case 2 -> objectMap.put(name, data.consumeBytes(100)); + case 3 -> objectMap.put(name, data.consumeBoolean()); + } + } + + RequestContext context = new RequestContext(new DummyWebExchange(), objectMap, new DummyMessage()); + try { + BindStatus bindStatus = new BindStatus(context, data.consumeString(100), data.consumeBoolean()); + bindStatus.getActualValue(); + bindStatus.getEditor(); + bindStatus.getDisplayValue(); + bindStatus.getErrors(); + bindStatus.getErrorMessages(); + bindStatus.getPath(); + } catch (IllegalStateException | InvalidPropertyException e) {} + } + + // Mocked classes + public static class DummyMessage implements MessageSource { + + @Override + public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { + return null; + } + + @Override + public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { + return null; + } + + @Override + public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { + return null; + } + } + + + public static class DummyWebExchange implements ServerWebExchange { + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return new HashMap() {{ + put("foo", "bar"); + }}; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return new SimpleLocaleContext(new Locale("EN_us")); + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant lastModified) { + return false; + } + + @Override + public boolean checkNotModified(String etag) { + return false; + } + + @Override + public boolean checkNotModified(String etag, Instant lastModified) { + return false; + } + + @Override + public String transformUrl(String url) { + return null; + } + + @Override + public void addUrlTransformer(Function transformer) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } +}