diff options
author | 2017-07-18 17:04:44 -0700 | |
---|---|---|
committer | 2017-07-18 17:09:10 -0700 | |
commit | afb6962992b8e9e14e27989772519ee4fe38e851 (patch) | |
tree | 353cccd3aa8adb07a0c0b2913c4cecd6338de81f /tensorflow/core/kernels/fuzzing | |
parent | 06acccabcb41513c76bbfffcd17817a7b136494b (diff) |
Introduces fuzzers for some complex operations and kernels in TensorFlow in preparation for eventaul fuzzing using Google OSS-Fuzz.
PiperOrigin-RevId: 162425120
Diffstat (limited to 'tensorflow/core/kernels/fuzzing')
14 files changed, 678 insertions, 0 deletions
diff --git a/tensorflow/core/kernels/fuzzing/BUILD b/tensorflow/core/kernels/fuzzing/BUILD new file mode 100644 index 0000000000..3e7f9bdb44 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/BUILD @@ -0,0 +1,55 @@ +licenses(["notice"]) # Apache 2.0 + +package( + default_visibility = ["//visibility:public"], +) + +cc_library( + name = "fuzz_session", + hdrs = ["fuzz_session.h"], + deps = [ + "//tensorflow/cc:cc_ops", + "//tensorflow/cc:scope", + "//tensorflow/core:all_kernels", + "//tensorflow/core:core_cpu", + "//tensorflow/core:direct_session", + "//tensorflow/core:ops", + "//tensorflow/core:tensorflow", + ], +) + +filegroup( + name = "all_files", + srcs = glob( + ["**/*"], + exclude = [ + "**/METADATA", + "**/OWNERS", + ], + ), + visibility = ["//tensorflow:__subpackages__"], +) + +load("//tensorflow/core/kernels/fuzzing:tf_ops_fuzz_target_lib.bzl", "tf_ops_fuzz_target_lib") + +tf_ops_fuzz_target_lib("identity") + +tf_ops_fuzz_target_lib("string_to_number") + +tf_ops_fuzz_target_lib("string_split") + +tf_ops_fuzz_target_lib("encode_base64") + +tf_ops_fuzz_target_lib("decode_base64") + +tf_ops_fuzz_target_lib("encode_jpeg") + +tf_ops_fuzz_target_lib("decode_png") + +tf_ops_fuzz_target_lib("decode_jpeg") + +tf_ops_fuzz_target_lib("example_proto_fast_parsing") + +tf_ops_fuzz_target_lib("parse_tensor_op") + +tf_ops_fuzz_target_lib("decode_json_example") diff --git a/tensorflow/core/kernels/fuzzing/decode_base64_fuzz.cc b/tensorflow/core/kernels/fuzzing/decode_base64_fuzz.cc new file mode 100644 index 0000000000..6d4a9dfdef --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/decode_base64_fuzz.cc @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzDecodeBase64 : public FuzzStringInputOp { + SINGLE_INPUT_OP_BUILDER(DT_STRING, DecodeBase64); +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzDecodeBase64); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/decode_jpeg_fuzz.cc b/tensorflow/core/kernels/fuzzing/decode_jpeg_fuzz.cc new file mode 100644 index 0000000000..b084a97204 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/decode_jpeg_fuzz.cc @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzDecodeJpeg : public FuzzStringInputOp { + SINGLE_INPUT_OP_BUILDER(DT_STRING, DecodeJpeg); +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzDecodeJpeg); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/decode_json_example_fuzz.cc b/tensorflow/core/kernels/fuzzing/decode_json_example_fuzz.cc new file mode 100644 index 0000000000..9dd795b94e --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/decode_json_example_fuzz.cc @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzDecodeJSONExample : public FuzzStringInputOp { + SINGLE_INPUT_OP_BUILDER(DT_STRING, DecodeJSONExample); +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzDecodeJSONExample); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/decode_png_fuzz.cc b/tensorflow/core/kernels/fuzzing/decode_png_fuzz.cc new file mode 100644 index 0000000000..4a68a5b580 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/decode_png_fuzz.cc @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzDecodePng : public FuzzStringInputOp { + SINGLE_INPUT_OP_BUILDER(DT_STRING, DecodePng); +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzDecodePng); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc b/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc new file mode 100644 index 0000000000..2d6c82826c --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzEncodeBase64 : public FuzzSession { + SINGLE_INPUT_OP_BUILDER(DT_STRING, EncodeBase64); +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzEncodeBase64); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/encode_jpeg_fuzz.cc b/tensorflow/core/kernels/fuzzing/encode_jpeg_fuzz.cc new file mode 100644 index 0000000000..81b6e49124 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/encode_jpeg_fuzz.cc @@ -0,0 +1,63 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzEncodeJpeg : public FuzzSession { + SINGLE_INPUT_OP_BUILDER(DT_UINT8, EncodeJpeg); + + void FuzzImpl(const uint8_t* data, size_t size) final { + if (size < 6) return; + + // Pick random channels and aspect ratio, and then set the + // input based upon the aspect ratio and size. + int64 channels = (data[0] % 2) * 2 + 1; // 1, 3 + int64 height = data[1] + (data[2] << 8); + int64 width = data[2] + (data[3] << 8); + if (width == 0) return; + + // TODO(dga): kcc@ notes: better to use actual supplied h, w and then + // trim them if needed to ensure w*h <= size-4. + double hw_ratio = height / width; + int64 remaining_bytes = size - 5; + int64 pixels = remaining_bytes / channels; + height = static_cast<int64>(floor(sqrt(hw_ratio * pixels))); + if (height == 0) return; + width = static_cast<int64>(floor(pixels / height)); + if (width == 0) return; + size_t actual_pixels = height * width * channels; + if (actual_pixels == 0) return; + + // TODO(dga): Generalize this by borrowing the AsTensor logic + // from tf testing, once we have a few more fuzzers written. + Tensor input_tensor(tensorflow::DT_UINT8, + TensorShape({height, width, channels})); + auto flat_tensor = input_tensor.flat<uint8>(); + for (size_t i = 0; i < actual_pixels; i++) { + flat_tensor(i) = data[i]; + } + // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object! + RunOneInput(input_tensor).IgnoreError(); + } +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzEncodeJpeg); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/example_proto_fast_parsing_fuzz.cc b/tensorflow/core/kernels/fuzzing/example_proto_fast_parsing_fuzz.cc new file mode 100644 index 0000000000..d91a351c59 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/example_proto_fast_parsing_fuzz.cc @@ -0,0 +1,64 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +// Fuzz inputs to the example proto decoder. +// TODO(dga): Make this more comprehensive. +// Right now, it's just a quick PoC to show how to attach the +// plumbing, but it needs some real protos to chew on as a +// corpus, and the sparse/dense parts should be made more rich +// to achieve higher code coverage. + +class FuzzExampleProtoFastParsing : public FuzzSession { + void BuildGraph(const Scope& scope) final { + using namespace ::tensorflow::ops; // NOLINT(build/namespaces) + // The serialized proto. + auto input = Placeholder(scope.WithOpName("input1"), DT_STRING); + + auto in_expanded = ExpandDims(scope, input, Const<int>(scope, 0)); + + auto names = Const(scope, {"noname"}); + std::vector<Output> dense_keys = {Const(scope, {"a"})}; + std::vector<Output> sparse_keys; // Empty. + std::vector<Output> dense_defaults = {Const(scope, {1.0f})}; + + DataTypeSlice sparse_types = {}; + std::vector<PartialTensorShape> dense_shapes; + dense_shapes.push_back(PartialTensorShape()); + + std::ignore = ParseExample(scope.WithOpName("output"), in_expanded, names, + sparse_keys, dense_keys, dense_defaults, + sparse_types, dense_shapes); + } + + void FuzzImpl(const uint8_t* data, size_t size) final { + // TODO(dga): Test the batch case also. + Tensor input_tensor(tensorflow::DT_STRING, TensorShape({})); + input_tensor.scalar<string>()() = + string(reinterpret_cast<const char*>(data), size); + // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object! + RunOneInput(input_tensor).IgnoreError(); + } +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzExampleProtoFastParsing); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/fuzz_session.h b/tensorflow/core/kernels/fuzzing/fuzz_session.h new file mode 100644 index 0000000000..fb518798b2 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/fuzz_session.h @@ -0,0 +1,156 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#ifndef LEARNING_BRAIN_KERNELS_FUZZING_FUZZ_SESSION_H_ +#define LEARNING_BRAIN_KERNELS_FUZZING_FUZZ_SESSION_H_ + +#include "tensorflow/cc/framework/scope.h" +#include "tensorflow/core/graph/graph.h" +#include "tensorflow/core/public/session.h" + +// Standard invoking function macro to dispatch to a fuzzer class. +#ifndef PLATFORM_WINDOWS +#define STANDARD_TF_FUZZ_FUNCTION(FuzzerClass) \ + extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { \ + static FuzzerClass* fuzzer = new FuzzerClass(); \ + return fuzzer->Fuzz(data, size); \ + } +#else +// We don't compile this for Windows, MSVC doesn't like it as pywrap in Windows +// links all the code into one big object file and there are conflicting +// function names. +#define STANDARD_TF_FUZZ_FUNCTION(FuzzerClass) +#endif + +// Standard builder for hooking one placeholder to one op. +#define SINGLE_INPUT_OP_BUILDER(dtype, opName) \ + void BuildGraph(const Scope& scope) override { \ + auto op_node = \ + tensorflow::ops::Placeholder(scope.WithOpName("input1"), dtype); \ + std::ignore = \ + tensorflow::ops::opName(scope.WithOpName("output"), op_node); \ + } + +namespace tensorflow { +namespace fuzzing { + +// Create a TensorFlow session using a specific GraphDef created +// by BuildGraph(), and make it available for fuzzing. +// Users must override BuildGraph and FuzzImpl to specify +// (1) which operations are being fuzzed; and +// (2) How to translate the uint8_t* buffer from the fuzzer +// to a Tensor or Tensors that are semantically appropriate +// for the op under test. +// For the simple cases of testing a single op that takes a single +// input Tensor, use the SINGLE_INPUT_OP_BUILDER(dtype, opName) macro in place +// of defining BuildGraphDef. +// +// Typical use: +// class FooFuzzer : public FuzzSession { +// SINGLE_INPUT_OP_BUILDER(DT_INT8, Identity); +// void FuzzImpl(const uint8_t* data, size_t size) { +// ... convert data and size to a Tensor, pass it to: +// RunOneInput(input_tensor); +// +class FuzzSession { + public: + FuzzSession() : initialized_(false) {} + virtual ~FuzzSession() {} + + // Constructs a Graph using the supplied Scope. + // By convention, the graph should have inputs named "input1", ... + // "inputN", and one output node, named "output". + // Users of FuzzSession should override this method to create their graph. + virtual void BuildGraph(const Scope& scope) {} + + // Implements the logic that converts an opaque byte buffer + // from the fuzzer to Tensor inputs to the graph. Users must override. + virtual void FuzzImpl(const uint8_t* data, size_t size) {} + + // Initializes the FuzzSession. Not safe for multithreading. + // Separate init function because the call to virtual BuildGraphDef + // can't be put into the constructor. + Status InitIfNeeded() { + if (initialized_) { + return Status::OK(); + } + initialized_ = true; + + Scope root = Scope::NewRootScope().ExitOnError(); + SessionOptions options; + session_ = std::unique_ptr<Session>(NewSession(options)); + + BuildGraph(root); + + GraphDef graph_def; + TF_CHECK_OK(root.ToGraphDef(&graph_def)); + + Status status = session_->Create(graph_def); + if (!status.ok()) { + // This is FATAL, because this code is designed to fuzz an op + // within a session. Failure to create the session means we + // can't send any data to the op. + LOG(FATAL) << "Could not create session: " << status.error_message(); + } + return status; + } + + // Runs the TF session by pulling on the "output" node, attaching + // the supplied input_tensor to the "input1" node, and discarding + // any returned output. + Status RunOneInput(const Tensor& input_tensor) { + return session_->Run({{"input1", input_tensor}}, {}, {"output"}, nullptr); + } + + Status RunTwoInputs(const Tensor& input1, const Tensor& input2) { + return session_->Run({{"input1", input1}, {"input2", input2}}, {}, + {"output"}, nullptr); + } + + // Dispatches to FuzzImpl; small amount of sugar to keep the code + // of the per-op fuzzers tiny. + int Fuzz(const uint8_t* data, size_t size) { + Status status = InitIfNeeded(); + TF_CHECK_OK(status) << "Fuzzer graph initialization failed: " + << status.error_message(); + // No return value from fuzzing: Success is defined as "did not + // crash". The actual application results are irrelevant. + FuzzImpl(data, size); + return 0; + } + + private: + bool initialized_; + std::unique_ptr<Session> session_; +}; + +// A specialized fuzz implementation for ops that take +// a single string. Caller must still define the op +// to plumb by overriding BuildGraph or using +// a plumbing macro. +class FuzzStringInputOp : public FuzzSession { + void FuzzImpl(const uint8_t* data, size_t size) final { + Tensor input_tensor(tensorflow::DT_STRING, TensorShape({})); + input_tensor.scalar<string>()() = + string(reinterpret_cast<const char*>(data), size); + // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object! + RunOneInput(input_tensor).IgnoreError(); + } +}; + +} // end namespace fuzzing +} // end namespace tensorflow + +#endif // LEARNING_BRAIN_KERNELS_FUZZING_FUZZ_SESSION_H_ diff --git a/tensorflow/core/kernels/fuzzing/identity_fuzz.cc b/tensorflow/core/kernels/fuzzing/identity_fuzz.cc new file mode 100644 index 0000000000..ac3a12aa39 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/identity_fuzz.cc @@ -0,0 +1,45 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzIdentity : public FuzzSession { + SINGLE_INPUT_OP_BUILDER(DT_INT8, Identity); + + void FuzzImpl(const uint8_t* data, size_t size) final { + Tensor input_tensor(tensorflow::DT_INT8, + TensorShape({static_cast<int64>(size)})); + auto flat_tensor = input_tensor.flat<int8>(); + for (size_t i = 0; i < size; i++) { + flat_tensor(i) = data[i]; + } + + Status s = RunOneInput(input_tensor); + // Note: For many ops, we don't care about this success -- but when + // testing to make sure the harness actually works, it's useful. + if (!s.ok()) { + LOG(ERROR) << "Execution failed: " << s.error_message(); + } + } +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzIdentity); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/parse_tensor_op_fuzz.cc b/tensorflow/core/kernels/fuzzing/parse_tensor_op_fuzz.cc new file mode 100644 index 0000000000..978fcd1028 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/parse_tensor_op_fuzz.cc @@ -0,0 +1,45 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +// Fuzz inputs to the serialized Tensor decoder. + +class FuzzParseTensor : public FuzzSession { + void BuildGraph(const Scope& scope) final { + using namespace ::tensorflow::ops; // NOLINT(build/namespaces) + // The serialized proto. + auto input = Placeholder(scope.WithOpName("input1"), DT_STRING); + + std::ignore = ParseTensor(scope.WithOpName("output"), input, DT_FLOAT); + } + + void FuzzImpl(const uint8_t* data, size_t size) final { + Tensor input_tensor(tensorflow::DT_STRING, TensorShape({})); + input_tensor.scalar<string>()() = + string(reinterpret_cast<const char*>(data), size); + // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object! + RunOneInput(input_tensor).IgnoreError(); + } +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzParseTensor); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc new file mode 100644 index 0000000000..7d1aa1fbf3 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc @@ -0,0 +1,60 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzStringSplit : public FuzzSession { + void BuildGraph(const Scope& scope) override { + auto input = + tensorflow::ops::Placeholder(scope.WithOpName("input1"), DT_STRING); + auto delimeter = + tensorflow::ops::Placeholder(scope.WithOpName("input2"), DT_STRING); + std::ignore = tensorflow::ops::StringSplit(scope.WithOpName("output"), + input, delimeter); + } + + void FuzzImpl(const uint8_t* data, size_t size) final { + Tensor input_tensor(tensorflow::DT_STRING, TensorShape({})); + Tensor delimeter_tensor(tensorflow::DT_STRING, TensorShape({})); + + if (size > 0) { + // The spec for split is that the delimeter should be 0 or 1 characters. + // Naturally, fuzz it with something larger. (This omits the possibility + // of handing it a > int32_max size string, which should be tested for in + // an + // explicit test). + size_t delim_len = static_cast<size_t>(data[0]); + if (delim_len > size) { + delim_len = size - 1; + } + delimeter_tensor.scalar<string>()() = + string(reinterpret_cast<const char*>(data), delim_len); + input_tensor.scalar<string>()() = string( + reinterpret_cast<const char*>(data + delim_len), size - delim_len); + } + + // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object! + RunTwoInputs(input_tensor, delimeter_tensor).IgnoreError(); + } +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzStringSplit); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/string_to_number_fuzz.cc b/tensorflow/core/kernels/fuzzing/string_to_number_fuzz.cc new file mode 100644 index 0000000000..94255d215e --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/string_to_number_fuzz.cc @@ -0,0 +1,32 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +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. +==============================================================================*/ + +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" +#include "tensorflow/cc/ops/standard_ops.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzStringToNumber : public FuzzStringInputOp { + SINGLE_INPUT_OP_BUILDER(DT_STRING, StringToNumber); +}; + +// TODO(dga): Generalize this to hit both the float and int +// variants of StringToNumber - requires an update to the +// plumbing code to specify the output dtype. +STANDARD_TF_FUZZ_FUNCTION(FuzzStringToNumber); + +} // end namespace fuzzing +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl b/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl new file mode 100644 index 0000000000..f752b59568 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl @@ -0,0 +1,13 @@ +"""Fuzzing template for TensorFlow ops.""" + +def tf_ops_fuzz_target_lib(name): + native.cc_library( + name = name + "_fuzz_lib", + srcs = [name + "_fuzz.cc"], + deps = [ + "//tensorflow/core/kernels/fuzzing:fuzz_session", + "//tensorflow/cc:cc_ops", + ], + tags = ["no_windows"], + alwayslink = 1, + ) |