diff --git a/projects/tensorflow-serving/Dockerfile b/projects/tensorflow-serving/Dockerfile new file mode 100644 index 000000000..cb64f4698 --- /dev/null +++ b/projects/tensorflow-serving/Dockerfile @@ -0,0 +1,38 @@ +# 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 +RUN apt-get update && apt-get install -y make autoconf automake libtool default-jdk bison m4 \ + build-essential\ + curl \ + doxygen \ + flex \ + libffi-dev \ + libncurses5-dev \ + libtool \ + libsqlite3-dev \ + mcpp \ + sqlite \ + uuid-runtime \ + zlib1g-dev +RUN python3 -m pip install numpy +RUN wget https://github.com/bazelbuild/buildtools/releases/download/4.2.5/buildifier-linux-amd64 \ + -O /usr/local/bin/buildifier && chmod a+x /usr/local/bin/buildifier + +RUN git clone https://github.com/tensorflow/serving serving + +COPY build.sh *.diff $SRC/ +WORKDIR $SRC/serving diff --git a/projects/tensorflow-serving/build.sh b/projects/tensorflow-serving/build.sh new file mode 100755 index 000000000..6e898aa4f --- /dev/null +++ b/projects/tensorflow-serving/build.sh @@ -0,0 +1,76 @@ +#!/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. +# +################################################################################ + +synchronize_coverage_directories() { + # For coverage, we need to remap source files to correspond to the Bazel build + # paths. We also need to resolve all symlinks that Bazel creates. + if [ "$SANITIZER" = "coverage" ] + then + declare -r RSYNC_CMD="rsync -aLkR" + declare -r REMAP_PATH=${OUT}/proc/self/cwd/ + mkdir -p ${REMAP_PATH} + + # Synchronize the folder bazel-BAZEL_OUT_PROJECT. + declare -r RSYNC_FILTER_ARGS=("--include" "*.h" "--include" "*.cc" "--include" \ + "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*/" "--include" "*.inc" \ + "--exclude" "*") + + # Sync existing code. + ${RSYNC_CMD} "${RSYNC_FILTER_ARGS[@]}" tensorflow_serving/ ${REMAP_PATH} + + # Sync generated proto files. + if [ -d "./bazel-out/k8-opt/bin/tensorflow/" ] + then + ${RSYNC_CMD} "${RSYNC_FILTER_ARGS[@]}" ./bazel-out/k8-opt/bin/tensorflow_serving/ ${REMAP_PATH} + fi + if [ -d "./bazel-out/k8-opt/bin/external" ] + then + ${RSYNC_CMD} "${RSYNC_FILTER_ARGS[@]}" ./bazel-out/k8-opt/bin/external/ ${REMAP_PATH} + fi + if [ -d "./bazel-out/k8-opt/bin/third_party" ] + then + ${RSYNC_CMD} "${RSYNC_FILTER_ARGS[@]}" ./bazel-out/k8-opt/bin/third_party/ ${REMAP_PATH} + fi + + # Sync external dependencies. We don't need to include `bazel-tensorflow`. + # Also, remove `external/org_tensorflow` which is a copy of the entire source + # code that Bazel creates. Not removing this would cause `rsync` to expand a + # symlink that ends up pointing to itself! + pushd bazel-serving + [[ -e external/org_tensorflow ]] && unlink external/org_tensorflow + ${RSYNC_CMD} external/ ${REMAP_PATH} + popd + fi +} + +git apply --ignore-space-change --ignore-whitespace $SRC/tensorflow-serving.diff + +bazel run @com_google_fuzztest//bazel:setup_configs >> /etc/bazel.bazelrc +bazel build --config=oss-fuzz --subcommands --spawn_strategy=sandboxed //tensorflow_serving/util:json_tensor_test_fuzz + +cp bazel-bin/tensorflow_serving/util/json_tensor_test_fuzz $OUT/json_tensor_test_fuzz + +TARGET_FUZZER="json_tensor_test_fuzz@JsonFuzzTest.TheF" +echo "#!/bin/sh +# LLVMFuzzerTestOneInput for fuzzer detection. +this_dir=\$(dirname \"\$0\") +chmod +x \$this_dir/json_tensor_test_fuzz +\$this_dir/json_tensor_test_fuzz --fuzz=JsonFuzzTest.TheF -- \$@" > $OUT/${TARGET_FUZZER} +chmod +x $OUT/${TARGET_FUZZER} + +# Synchronize coverage folders +synchronize_coverage_directories diff --git a/projects/tensorflow-serving/project.yaml b/projects/tensorflow-serving/project.yaml new file mode 100644 index 000000000..57642e96c --- /dev/null +++ b/projects/tensorflow-serving/project.yaml @@ -0,0 +1,9 @@ +homepage: "https://github.com/tensorflow/serving" +primary_contact: "david@adalogics.com" +main_repo: "https://github.com/tensorflow/serving" +language: c++ +sanitizers: + - address + - undefined +fuzzing_engines: + - libfuzzer diff --git a/projects/tensorflow-serving/tensorflow-serving.diff b/projects/tensorflow-serving/tensorflow-serving.diff new file mode 100644 index 000000000..b51fd704f --- /dev/null +++ b/projects/tensorflow-serving/tensorflow-serving.diff @@ -0,0 +1,81 @@ +diff --git a/tensorflow_serving/util/BUILD b/tensorflow_serving/util/BUILD +index 4802a79f..f7d596dc 100644 +--- a/tensorflow_serving/util/BUILD ++++ b/tensorflow_serving/util/BUILD +@@ -345,6 +345,28 @@ cc_test( + ], + ) + ++cc_test( ++ name = "json_tensor_test_fuzz", ++ srcs = ["json_tensor_test.cc"], ++ deps = [ ++ ":json_tensor", ++ "//tensorflow_serving/apis:classification_cc_proto", ++ "//tensorflow_serving/apis:model_cc_proto", ++ "//tensorflow_serving/apis:predict_cc_proto", ++ "//tensorflow_serving/apis:regression_cc_proto", ++ # "//tensorflow_serving/core/test_util:test_main", ++ "@org_tensorflow//tensorflow/core:testlib", ++ "//tensorflow_serving/test_util", ++ "@com_google_fuzztest//fuzztest", ++ "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", ++ "@com_google_protobuf//:protobuf", ++ "@org_tensorflow//tensorflow/core:framework", ++ "@org_tensorflow//tensorflow/core:lib", ++ "@org_tensorflow//tensorflow/core:protos_all_cc", ++ "@org_tensorflow//tensorflow/core:test", ++ ], ++) ++ + cc_library( + name = "proto_util", + srcs = ["proto_util.h"], +diff --git a/tensorflow_serving/util/json_tensor_test.cc b/tensorflow_serving/util/json_tensor_test.cc +index b8145986..2b6a464b 100644 +--- a/tensorflow_serving/util/json_tensor_test.cc ++++ b/tensorflow_serving/util/json_tensor_test.cc +@@ -23,6 +23,9 @@ limitations under the License. + #include + #include + #include "absl/strings/substitute.h" ++ ++#include "fuzztest/fuzztest.h" ++ + #include "tensorflow/core/lib/core/errors.h" + #include "tensorflow/core/lib/core/status_test_util.h" + #include "tensorflow/core/platform/protobuf.h" +@@ -184,6 +187,15 @@ TEST(JsontensorTest, FloatTensorWithPrecisionLoss) { + )")); + } + ++ ++void TheF(const std::string &s1) { ++ if (s1.size() > 120){ ++ TensorInfoMap infomap; ++ TextFormat::ParseFromString(s1, &infomap["default"]); ++ } ++} ++FUZZ_TEST(JsonFuzzTest, TheF); ++ + TEST(JsontensorTest, FloatTensorThatExceedsMaxReturnsInf) { + TensorInfoMap infomap; + ASSERT_TRUE( +diff --git a/tensorflow_serving/workspace.bzl b/tensorflow_serving/workspace.bzl +index de1203a7..dd18da94 100644 +--- a/tensorflow_serving/workspace.bzl ++++ b/tensorflow_serving/workspace.bzl +@@ -104,6 +104,13 @@ def tf_serving_workspace(): + ], + ) + ++ http_archive( ++ name = "com_google_fuzztest", ++ sha256 = "c75f224b34c3c62ee901381fb743f6326f7b91caae0ceb8fe62f3fd36f187627", ++ strip_prefix = "fuzztest-58b4e7065924f1a284952b84ea827ce35a87e4dc", ++ urls = ["https://github.com/google/fuzztest/archive/58b4e7065924f1a284952b84ea827ce35a87e4dc.zip"], ++ ) ++ + # ==== TensorFlow Decision Forests === + http_archive( + name = "org_tensorflow_decision_forests",