diff --git a/docs/new_library.md b/docs/new_library.md index cbb34d61864a..f1fada76c902 100644 --- a/docs/new_library.md +++ b/docs/new_library.md @@ -23,8 +23,8 @@ To create a new directory for a library: ```bash $ cd /path/to/oss-fuzz/checkout -$ python scripts/helper.py generate name_of_the_library $ export LIB_NAME=name_of_the_library +$ python scripts/helper.py generate $LIB_NAME ``` This script automatically creates these 3 files for you to fill in. diff --git a/re2/Dockerfile b/re2/Dockerfile new file mode 100644 index 000000000000..291762acac5a --- /dev/null +++ b/re2/Dockerfile @@ -0,0 +1,21 @@ +# Copyright 2016 Google Inc. +# +# 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 ossfuzz/base-libfuzzer +MAINTAINER wrengr@chromium.org +RUN apt-get install -y make autoconf automake libtool + +CMD /src/oss-fuzz/re2/build.sh diff --git a/re2/Jenkinsfile b/re2/Jenkinsfile new file mode 100644 index 000000000000..689fab06f806 --- /dev/null +++ b/re2/Jenkinsfile @@ -0,0 +1,23 @@ +// Copyright 2016 Google Inc. +// +// 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. +// +//////////////////////////////////////////////////////////////////////////////// + +def libfuzzerBuild = fileLoader.fromGit('infra/libfuzzer-pipeline.groovy', + 'https://github.com/google/oss-fuzz.git', + 'master', null, '') + +libfuzzerBuild { + git = "https://code.googlesource.com/re2" +} diff --git a/re2/build.sh b/re2/build.sh new file mode 100755 index 000000000000..27bc60799d7d --- /dev/null +++ b/re2/build.sh @@ -0,0 +1,36 @@ +#!/bin/bash -eu +# Copyright 2016 Google Inc. +# +# 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. +# +################################################################################ + +cd /src/re2 + +# First, build the re2 library. +# N.B., we don't follow the standard incantation for building re2 +# (i.e., `make && make test && make install && make testinstall`), +# because some of the targets doesn't use $CXXFLAGS properly, which +# causes compilation to fail. The obj/libre2.a target is all we +# really need for our fuzzer, so that's all we build. Hopefully +# this won't cause the fuzzer to fail erroneously due to not running +# upstream's tests first to be sure things compiled correctly. +make clean +make obj/libre2.a + + +# Second, build our fuzzers. +$CXX $CXXFLAGS -std=c++11 -I. \ + /src/oss-fuzz/re2/re2_fuzzer.cc -o /out/re2_fuzzer \ + /work/libfuzzer/*.o ./obj/libre2.a $LDFLAGS + diff --git a/re2/re2.options b/re2/re2.options new file mode 100644 index 000000000000..ea2785e1104a --- /dev/null +++ b/re2/re2.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 32 diff --git a/re2/re2_fuzzer.cc b/re2/re2_fuzzer.cc new file mode 100644 index 000000000000..9c16462a24d8 --- /dev/null +++ b/re2/re2_fuzzer.cc @@ -0,0 +1,87 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include + +#include "re2/re2.h" +#include "util/logging.h" + +using std::string; + +void Test(const string& buffer, const string& pattern, + const RE2::Options& options) { + RE2 re(pattern, options); + if (!re.ok()) + return; + + string m1, m2; + int i1, i2; + double d1; + + if (re.NumberOfCapturingGroups() == 0) { + RE2::FullMatch(buffer, re); + RE2::PartialMatch(buffer, re); + } else if (re.NumberOfCapturingGroups() == 1) { + RE2::FullMatch(buffer, re, &m1); + RE2::PartialMatch(buffer, re, &i1); + } else if (re.NumberOfCapturingGroups() == 2) { + RE2::FullMatch(buffer, re, &i1, &i2); + RE2::PartialMatch(buffer, re, &m1, &m2); + } + + re2::StringPiece input(buffer); + RE2::Consume(&input, re, &m1); + RE2::FindAndConsume(&input, re, &d1); + string tmp1(buffer); + RE2::Replace(&tmp1, re, "zz"); + string tmp2(buffer); + RE2::GlobalReplace(&tmp2, re, "xx"); + RE2::QuoteMeta(re2::StringPiece(pattern)); +} + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 1) + return 0; + + RE2::Options options; + + size_t options_randomizer = 0; + for (size_t i = 0; i < size; i++) + options_randomizer += data[i]; + + if (options_randomizer & 1) + options.set_encoding(RE2::Options::EncodingLatin1); + + options.set_posix_syntax(options_randomizer & 2); + options.set_longest_match(options_randomizer & 4); + options.set_literal(options_randomizer & 8); + options.set_never_nl(options_randomizer & 16); + options.set_dot_nl(options_randomizer & 32); + options.set_never_capture(options_randomizer & 64); + options.set_case_sensitive(options_randomizer & 128); + options.set_perl_classes(options_randomizer & 256); + options.set_word_boundary(options_randomizer & 512); + options.set_one_line(options_randomizer & 1024); + + options.set_log_errors(false); + + const char* data_input = reinterpret_cast(data); + { + string pattern(data_input, size); + string buffer(data_input, size); + Test(buffer, pattern, options); + } + + if (size >= 3) { + string pattern(data_input, size / 3); + string buffer(data_input + size / 3, size - size / 3); + Test(buffer, pattern, options); + } + + return 0; +}