diff --git a/.licenserc.yaml b/.licenserc.yaml index 042769f140..b6fac1f0b0 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -214,4 +214,7 @@ header: # NGINX - 'src/brpc/details/http_parser.*' + # Fuzzing seed + - 'test/fuzzing/fuzz_*_seed_corpus/*' + comment: on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index a01a0bf6b4..2d23f7396d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ option(WITH_THRIFT "With thrift framed protocol supported" OFF) option(WITH_SNAPPY "With snappy" OFF) option(WITH_RDMA "With RDMA" OFF) option(BUILD_UNIT_TESTS "Whether to build unit tests" OFF) +option(BUILD_FUZZ_TESTS "Whether to build fuzz tests" OFF) option(BUILD_BRPC_TOOLS "Whether to build brpc tools" ON) option(DOWNLOAD_GTEST "Download and build a fresh copy of googletest. Requires Internet access." ON) @@ -478,6 +479,15 @@ if(BUILD_UNIT_TESTS) add_subdirectory(test) endif() +if(BUILD_FUZZ_TESTS) + if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(FATAL_ERROR "Fuzzing is only supported with clang") + endif() + if(NOT BUILD_UNIT_TESTS) + message(FATAL_ERROR "BUILD_UNIT_TESTS must be enabled to build fuzz tests") + endif() +endif() + if(BUILD_BRPC_TOOLS) add_subdirectory(tools) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index aa441d27f6..25f94bfd09 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -51,7 +51,7 @@ else() message(FATAL_ERROR "Googletest is not available") endif() -set(CMAKE_CPP_FLAGS "${DEFINE_CLOCK_GETTIME} -DBRPC_WITH_GLOG=${WITH_GLOG_VAL} -DBRPC_WITH_RDMA=${WITH_RDMA_VAL} -DGFLAGS_NS=${GFLAGS_NS}") +set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} ${DEFINE_CLOCK_GETTIME} -DBRPC_WITH_GLOG=${WITH_GLOG_VAL} -DBRPC_WITH_RDMA=${WITH_RDMA_VAL} -DGFLAGS_NS=${GFLAGS_NS}") set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -DBTHREAD_USE_FAST_PTHREAD_MUTEX -D__const__=__unused__ -D_GNU_SOURCE -DUSE_SYMBOLIZE -DNO_TCMALLOC -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DUNIT_TEST -Dprivate=public -Dprotected=public -DBVAR_NOT_LINK_DEFAULT_VARIABLES -D__STRICT_ANSI__ -include ${PROJECT_SOURCE_DIR}/test/sstream_workaround.h") set(CMAKE_CXX_FLAGS "${CMAKE_CPP_FLAGS} -g -O2 -pipe -Wall -W -fPIC -fstrict-aliasing -Wno-invalid-offsetof -Wno-unused-parameter -fno-omit-frame-pointer") use_cxx11() @@ -253,3 +253,28 @@ foreach(BRPC_UT ${BRPC_UNITTESTS}) ${GPERFTOOLS_LIBRARIES}) add_test(NAME ${BRPC_UT_WE} COMMAND ${BRPC_UT_WE}) endforeach() + +if(BUILD_FUZZ_TESTS) + add_library(brpc-static-debug STATIC $ + $ + $) + # change the debug lib output dir to be different from the release output + set_target_properties(brpc-static-debug PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/test) + + target_link_libraries(brpc-static-debug ${DYNAMIC_LIB}) + if(BRPC_WITH_GLOG) + target_link_libraries(brpc-static-debug ${GLOG_LIB}) + endif() + + set(FUZZ_TARGETS fuzz_butil fuzz_esp fuzz_hpack fuzz_http + fuzz_hulu fuzz_json fuzz_redis fuzz_shead fuzz_sofa fuzz_uri) + + foreach(target ${FUZZ_TARGETS}) + add_executable(${target} fuzzing/${target}.cpp $) + target_link_libraries(${target} brpc-static-debug ${LIB_FUZZING_ENGINE}) + set_target_properties(${target} PROPERTIES + BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH "$ORIGIN/lib") + endforeach() +endif() diff --git a/test/fuzzing/fuzz_butil.cpp b/test/fuzzing/fuzz_butil.cpp new file mode 100644 index 0000000000..470d1e99e0 --- /dev/null +++ b/test/fuzzing/fuzz_butil.cpp @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "butil/base64.h" +#include "butil/crc32c.h" +#include "butil/hash.h" +#include "butil/sha1.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + { + std::string encoded; + std::string decoded; + butil::Base64Encode(input, &encoded); + butil::Base64Decode(input, &decoded); + } + { + butil::crc32c::Value(reinterpret_cast(data), size); + } + { + butil::Hash(input); + } + { + butil::SHA1HashString(input); + } + + return 0; +} diff --git a/test/fuzzing/fuzz_butil_seed_corpus/base64_decoded.txt b/test/fuzzing/fuzz_butil_seed_corpus/base64_decoded.txt new file mode 100644 index 0000000000..771f0755ed --- /dev/null +++ b/test/fuzzing/fuzz_butil_seed_corpus/base64_decoded.txt @@ -0,0 +1 @@ +aGVsbG8gd29ybGQ= diff --git a/test/fuzzing/fuzz_butil_seed_corpus/base64_encoded.txt b/test/fuzzing/fuzz_butil_seed_corpus/base64_encoded.txt new file mode 100644 index 0000000000..3b18e512db --- /dev/null +++ b/test/fuzzing/fuzz_butil_seed_corpus/base64_encoded.txt @@ -0,0 +1 @@ +hello world diff --git a/test/fuzzing/fuzz_butil_seed_corpus/crc32c.data b/test/fuzzing/fuzz_butil_seed_corpus/crc32c.data new file mode 100644 index 0000000000..7e12119537 Binary files /dev/null and b/test/fuzzing/fuzz_butil_seed_corpus/crc32c.data differ diff --git a/test/fuzzing/fuzz_esp.cpp b/test/fuzzing/fuzz_esp.cpp new file mode 100644 index 0000000000..462aaf8b55 --- /dev/null +++ b/test/fuzzing/fuzz_esp.cpp @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/policy/esp_protocol.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + butil::IOBuf buf; + buf.append(input); + + brpc::policy::ParseEspMessage(&buf, NULL, false, NULL); + + return 0; +} diff --git a/test/fuzzing/fuzz_hpack.cpp b/test/fuzzing/fuzz_hpack.cpp new file mode 100644 index 0000000000..0ee8131aac --- /dev/null +++ b/test/fuzzing/fuzz_hpack.cpp @@ -0,0 +1,43 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/details/hpack.h" +#include "butil/logging.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + butil::IOBuf buf; + brpc::HPacker p2; + brpc::HPacker::Header h2; + + p2.Init(4096); + buf.append(input); + + p2.Decode(&buf, &h2); + + return 0; +} diff --git a/test/fuzzing/fuzz_hpack_seed_corpus/header_never_indexed.hpack b/test/fuzzing/fuzz_hpack_seed_corpus/header_never_indexed.hpack new file mode 100644 index 0000000000..b8cfac03b0 --- /dev/null +++ b/test/fuzzing/fuzz_hpack_seed_corpus/header_never_indexed.hpack @@ -0,0 +1 @@ +passwordsecret \ No newline at end of file diff --git a/test/fuzzing/fuzz_hpack_seed_corpus/header_with_indexing.hpack b/test/fuzzing/fuzz_hpack_seed_corpus/header_with_indexing.hpack new file mode 100644 index 0000000000..3d994aa42e --- /dev/null +++ b/test/fuzzing/fuzz_hpack_seed_corpus/header_with_indexing.hpack @@ -0,0 +1,2 @@ +@ +custom-key custom-header \ No newline at end of file diff --git a/test/fuzzing/fuzz_hpack_seed_corpus/header_without_indexing.hpack b/test/fuzzing/fuzz_hpack_seed_corpus/header_without_indexing.hpack new file mode 100644 index 0000000000..0f91566fa4 --- /dev/null +++ b/test/fuzzing/fuzz_hpack_seed_corpus/header_without_indexing.hpack @@ -0,0 +1 @@ + /sample/path \ No newline at end of file diff --git a/test/fuzzing/fuzz_hpack_seed_corpus/requests_without_huffman.hpack b/test/fuzzing/fuzz_hpack_seed_corpus/requests_without_huffman.hpack new file mode 100644 index 0000000000..4a32d9882e --- /dev/null +++ b/test/fuzzing/fuzz_hpack_seed_corpus/requests_without_huffman.hpack @@ -0,0 +1,2 @@ +‚‡…¿@ +custom-key custom-value \ No newline at end of file diff --git a/test/fuzzing/fuzz_hpack_seed_corpus/responses_without_huffman.hpack b/test/fuzzing/fuzz_hpack_seed_corpus/responses_without_huffman.hpack new file mode 100644 index 0000000000..5bda49df8c --- /dev/null +++ b/test/fuzzing/fuzz_hpack_seed_corpus/responses_without_huffman.hpack @@ -0,0 +1 @@ +H302XprivateaMon, 21 Oct 2013 20:13:21 GMTnhttps://www.example.com \ No newline at end of file diff --git a/test/fuzzing/fuzz_http.cpp b/test/fuzzing/fuzz_http.cpp new file mode 100644 index 0000000000..c621d504f7 --- /dev/null +++ b/test/fuzzing/fuzz_http.cpp @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/details/http_message.h" +#include "brpc/policy/http_rpc_protocol.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + { + butil::IOBuf buf; + buf.append(input); + brpc::HttpMessage http_message; + http_message.ParseFromIOBuf(buf); + } + { + brpc::HttpMessage http_message; + http_message.ParseFromArray((char *)data, size); + } + + return 0; +} diff --git a/test/fuzzing/fuzz_http_seed_corpus/http_request.http b/test/fuzzing/fuzz_http_seed_corpus/http_request.http new file mode 100644 index 0000000000..1d056626ec --- /dev/null +++ b/test/fuzzing/fuzz_http_seed_corpus/http_request.http @@ -0,0 +1,9 @@ +GET /path/file.html?sdfsdf=sdfs HTTP/1.0 +From: someuser@jmarshall.com +User-Agent: HTTPTool/1.0 +Content-Type: json +Content-Length: 19 +Host: sdlfjslfd +Accept: */* + +Message Body sdfsdf diff --git a/test/fuzzing/fuzz_http_seed_corpus/http_request_v2.http b/test/fuzzing/fuzz_http_seed_corpus/http_request_v2.http new file mode 100644 index 0000000000..9923cd2d8f --- /dev/null +++ b/test/fuzzing/fuzz_http_seed_corpus/http_request_v2.http @@ -0,0 +1,23 @@ +GET /CloudApiControl/HttpServer/telematics/v3/weather?location=%E6%B5%B7%E5%8D%97%E7%9C%81%E7%9B%B4%E8%BE%96%E5%8E%BF%E7%BA%A7%E8%A1%8C%E6%94%BF%E5%8D%95%E4%BD%8D&output=json&ak=0l3FSP6qA0WbOzGRaafbmczS HTTP/1.1 +X-Host: api.map.baidu.com +X-Forwarded-Proto: http +Host: api.map.baidu.com +User-Agent: IME/Android/4.4.2/N80.QHD.LT.X10.V3/N80.QHD.LT.X10.V3.20150812.031915 +Accept: application/json +Accept-Charset: UTF-8,*;q=0.5 +Accept-Encoding: deflate,sdch +Accept-Language: zh-CN,en-US;q=0.8,zh;q=0.6 +Bfe-Atk: NORMAL_BROWSER +Bfe_logid: 8767802212038413243 +Bfeip: 10.26.124.40 +CLIENTIP: 119.29.102.26 +CLIENTPORT: 59863 +Cache-Control: max-age=0 +Content-Type: application/json;charset=utf8 +X-Forwarded-For: 119.29.102.26 +X-Forwarded-Port: 59863 +X-Ime-Imei: 35629601890905 +X_BD_LOGID: 3959476981 +X_BD_LOGID64: 16815814797661447369 +X_BD_PRODUCT: map +X_BD_SUBSYS: apimap diff --git a/test/fuzzing/fuzz_hulu.cpp b/test/fuzzing/fuzz_hulu.cpp new file mode 100644 index 0000000000..f90d7be864 --- /dev/null +++ b/test/fuzzing/fuzz_hulu.cpp @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/policy/hulu_pbrpc_protocol.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + butil::IOBuf buf; + buf.append(input); + + brpc::policy::ParseHuluMessage(&buf, NULL, false, NULL); + + return 0; +} diff --git a/test/fuzzing/fuzz_json.cpp b/test/fuzzing/fuzz_json.cpp new file mode 100644 index 0000000000..3a0335f523 --- /dev/null +++ b/test/fuzzing/fuzz_json.cpp @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "json2pb/json_to_pb.h" +#include "addressbook1.pb.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string error; + JsonContextBody jsondata; + std::string input_data((char *)data,size); + json2pb::JsonToProtoMessage(input_data, &jsondata, &error); + + return 0; +} diff --git a/test/fuzzing/fuzz_json_seed_corpus/info1.json b/test/fuzzing/fuzz_json_seed_corpus/info1.json new file mode 100644 index 0000000000..c708dc156f --- /dev/null +++ b/test/fuzzing/fuzz_json_seed_corpus/info1.json @@ -0,0 +1 @@ +{"judge":false, "spur":-2, "data":[], "info":[],"content":[]} \ No newline at end of file diff --git a/test/fuzzing/fuzz_json_seed_corpus/info2.json b/test/fuzzing/fuzz_json_seed_corpus/info2.json new file mode 100644 index 0000000000..43aee79ea1 --- /dev/null +++ b/test/fuzzing/fuzz_json_seed_corpus/info2.json @@ -0,0 +1 @@ +[{"container": 1000, "host": 1000, "size": 2}] \ No newline at end of file diff --git a/test/fuzzing/fuzz_json_seed_corpus/info3.json b/test/fuzzing/fuzz_json_seed_corpus/info3.json new file mode 100644 index 0000000000..db63ece2bc --- /dev/null +++ b/test/fuzzing/fuzz_json_seed_corpus/info3.json @@ -0,0 +1 @@ +{"content":[{"distance":1,"unknown_member":2,"ext":{"age":1666666666, "databyte":"d2VsY29tZQ==", "enumtype":1},"uid":"someone"},{"distance":10,"unknown_member":20,"ext":{"age":1666666660, "databyte":"d2VsY29tZQ==","enumtype":2},"uid":"someone0"}], "judge":false,"spur":2, "data":[1,2,3,4,5,6,7,8,9,10]} \ No newline at end of file diff --git a/test/fuzzing/fuzz_redis.cpp b/test/fuzzing/fuzz_redis.cpp new file mode 100644 index 0000000000..6f4368dccc --- /dev/null +++ b/test/fuzzing/fuzz_redis.cpp @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +#include + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + butil::IOBuf buf; + buf.append(input); + { + butil::Arena arena; + brpc::RedisCommandParser parser; + std::vector command_out; + parser.Consume(buf, &command_out, &arena); + } + { + butil::Arena arena; + brpc::RedisReply r2(&arena); + r2.ConsumePartialIOBuf(buf); + } + + return 0; +} + diff --git a/test/fuzzing/fuzz_redis_seed_corpus/command_parser.redis b/test/fuzzing/fuzz_redis_seed_corpus/command_parser.redis new file mode 100644 index 0000000000..7b013c6727 --- /dev/null +++ b/test/fuzzing/fuzz_redis_seed_corpus/command_parser.redis @@ -0,0 +1,7 @@ +*3 +$3 +set +$3 +abc +$3 +def diff --git a/test/fuzzing/fuzz_redis_seed_corpus/request.redis b/test/fuzzing/fuzz_redis_seed_corpus/request.redis new file mode 100644 index 0000000000..382063d743 --- /dev/null +++ b/test/fuzzing/fuzz_redis_seed_corpus/request.redis @@ -0,0 +1 @@ +set a '' \ No newline at end of file diff --git a/test/fuzzing/fuzz_shead.cpp b/test/fuzzing/fuzz_shead.cpp new file mode 100644 index 0000000000..2abf517b8c --- /dev/null +++ b/test/fuzzing/fuzz_shead.cpp @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/policy/public_pbrpc_meta.pb.h" +#include "brpc/policy/public_pbrpc_protocol.h" +#include "brpc/policy/most_common_message.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + butil::IOBuf buf; + buf.append(input); + + brpc::policy::ParseNsheadMessage(&buf, NULL, false, NULL); + + return 0; +} diff --git a/test/fuzzing/fuzz_sofa.cpp b/test/fuzzing/fuzz_sofa.cpp new file mode 100644 index 0000000000..e26f6218cb --- /dev/null +++ b/test/fuzzing/fuzz_sofa.cpp @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/policy/sofa_pbrpc_meta.pb.h" +#include "brpc/policy/sofa_pbrpc_protocol.h" +#include "brpc/policy/most_common_message.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + std::string input(reinterpret_cast(data), size); + + butil::IOBuf buf; + buf.append(input); + + brpc::policy::ParseSofaMessage(&buf, NULL, false, NULL); + return 0; +} diff --git a/test/fuzzing/fuzz_uri.cpp b/test/fuzzing/fuzz_uri.cpp new file mode 100644 index 0000000000..3db1dec214 --- /dev/null +++ b/test/fuzzing/fuzz_uri.cpp @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 "brpc/uri.h" +#include "brpc/rtmp.h" + +#define kMinInputLength 5 +#define kMaxInputLength 1024 + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength){ + return 1; + } + + char *data_in = (char *)malloc(size + 1); + memcpy(data_in, data, size); + data_in[size] = '\0'; + + + std::string input(reinterpret_cast(data), size); + { + brpc::URI uri; + uri.SetHttpURL(input); + } + { + butil::StringPiece host; + butil::StringPiece vhost; + butil::StringPiece port; + butil::StringPiece app; + butil::StringPiece stream_name; + + brpc::ParseRtmpURL(input, &host, &vhost, &port, &app, &stream_name); + } + + return 0; +} diff --git a/test/fuzzing/fuzz_uri_seed_corpus/data_1.rtmp b/test/fuzzing/fuzz_uri_seed_corpus/data_1.rtmp new file mode 100644 index 0000000000..561683e509 --- /dev/null +++ b/test/fuzzing/fuzz_uri_seed_corpus/data_1.rtmp @@ -0,0 +1 @@ +rtmp://HOST:8765//APP?vhost=abc///STREAM?queries diff --git a/test/fuzzing/fuzz_uri_seed_corpus/data_1.uri b/test/fuzzing/fuzz_uri_seed_corpus/data_1.uri new file mode 100644 index 0000000000..b87dbc6846 --- /dev/null +++ b/test/fuzzing/fuzz_uri_seed_corpus/data_1.uri @@ -0,0 +1 @@ +www.baidu2.com/s?wd=uri2&nonkey=22#frag diff --git a/test/fuzzing/fuzz_uri_seed_corpus/data_2.uri b/test/fuzzing/fuzz_uri_seed_corpus/data_2.uri new file mode 100644 index 0000000000..da343cbb7f --- /dev/null +++ b/test/fuzzing/fuzz_uri_seed_corpus/data_2.uri @@ -0,0 +1 @@ +http://user:passwd@a.b.c/?d=c&a=b&e=f#frg1 diff --git a/test/fuzzing/oss-fuzz.sh b/test/fuzzing/oss-fuzz.sh new file mode 100644 index 0000000000..f959b70b74 --- /dev/null +++ b/test/fuzzing/oss-fuzz.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +if [ "$SANITIZER" = "undefined" ] +then + sed -i '/static void DoProfiling/i __attribute__((no_sanitize("undefined")))' src/brpc/builtin/hotspots_service.cpp + sed -i '/void PProfService::heap/i __attribute__((no_sanitize("undefined")))' src/brpc/builtin/pprof_service.cpp + sed -i '/void PProfService::growth/i __attribute__((no_sanitize("undefined")))' src/brpc/builtin/pprof_service.cpp +fi + +mkdir -p build && cd build + +cmake \ + -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \ + -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CFLAGS" -DCMAKE_CPP_FLAGS="$CFLAGS" \ + -DCMAKE_EXE_LINKER_FLAGS="$CFLAGS" -DLIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" \ + -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -DWITH_SNAPPY=ON -DBUILD_UNIT_TESTS=ON -DBUILD_FUZZ_TESTS=ON ../. + +# https://github.com/google/oss-fuzz/pull/10898 +make \ + fuzz_butil fuzz_esp fuzz_hpack fuzz_http fuzz_hulu fuzz_json \ + fuzz_redis fuzz_shead fuzz_sofa fuzz_uri --ignore-errors -j$(nproc) + +cp test/fuzz_* $OUT/ + +pushd /lib/x86_64-linux-gnu/ +mkdir -p $OUT/lib/ +cp libgflags* libprotobuf* libleveldb* libprotoc* libsnappy* $OUT/lib/. +popd + +pushd $SRC/brpc/test/fuzzing +zip $OUT/fuzz_json_seed_corpus.zip fuzz_json_seed_corpus/* +zip $OUT/fuzz_uri_seed_corpus.zip fuzz_uri_seed_corpus/* +zip $OUT/fuzz_redis_seed_corpus.zip fuzz_redis_seed_corpus/* +zip $OUT/fuzz_http_seed_corpus.zip fuzz_http_seed_corpus/* +zip $OUT/fuzz_butil_seed_corpus.zip fuzz_butil_seed_corpus/* +zip $OUT/fuzz_hpack_seed_corpus.zip fuzz_hpack_seed_corpus/* +popd