Skip to content

Commit 625843e

Browse files
authored
Merge pull request #3254 from DavidKorczynski/extend-oss-fuzz
Extend fuzz harness suite and fix false positive
2 parents c16fdc6 + 4f94d25 commit 625843e

15 files changed

Lines changed: 468 additions & 6 deletions

test/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ if(BUILD_FUZZ_TESTS)
275275
endif()
276276

277277
set(FUZZ_TARGETS fuzz_butil fuzz_esp fuzz_hpack fuzz_http
278-
fuzz_hulu fuzz_json fuzz_redis fuzz_shead fuzz_sofa fuzz_uri)
278+
fuzz_hulu fuzz_json fuzz_redis fuzz_shead fuzz_sofa fuzz_uri
279+
fuzz_baidu_rpc fuzz_mongo fuzz_memcache
280+
fuzz_couchbase fuzz_streaming fuzz_http_parser fuzz_amf)
281+
279282

280283
foreach(target ${FUZZ_TARGETS})
281284
add_executable(${target} fuzzing/${target}.cpp $<TARGET_OBJECTS:TEST_PROTO_LIB>)

test/fuzzing/fuzz_amf.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "brpc/amf.h"
19+
#include "butil/iobuf.h"
20+
21+
#define kMinInputLength 5
22+
#define kMaxInputLength 4096
23+
24+
extern "C" int
25+
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
26+
{
27+
if (size < kMinInputLength || size > kMaxInputLength){
28+
return 1;
29+
}
30+
31+
uint8_t mode = data[0] % 3;
32+
const uint8_t *payload = data + 1;
33+
size_t payload_size = size - 1;
34+
35+
butil::IOBuf buf;
36+
buf.append(payload, payload_size);
37+
38+
switch (mode) {
39+
case 0: {
40+
// Read AMF object
41+
butil::IOBufAsZeroCopyInputStream zc_stream(buf);
42+
brpc::AMFInputStream stream(&zc_stream);
43+
brpc::AMFObject obj;
44+
brpc::ReadAMFObject(&obj, &stream);
45+
break;
46+
}
47+
case 1: {
48+
// Read AMF string
49+
butil::IOBufAsZeroCopyInputStream zc_stream(buf);
50+
brpc::AMFInputStream stream(&zc_stream);
51+
std::string val;
52+
brpc::ReadAMFString(&val, &stream);
53+
break;
54+
}
55+
case 2: {
56+
// Read raw AMF fields by consuming the stream directly
57+
butil::IOBufAsZeroCopyInputStream zc_stream(buf);
58+
brpc::AMFInputStream stream(&zc_stream);
59+
uint8_t marker;
60+
while (stream.good() && stream.cut_u8(&marker) == 1) {
61+
// Try to identify marker type and read value
62+
if (marker == brpc::AMF_MARKER_NUMBER) {
63+
uint64_t num;
64+
stream.cut_u64(&num);
65+
} else if (marker == brpc::AMF_MARKER_BOOLEAN) {
66+
uint8_t b;
67+
stream.cut_u8(&b);
68+
} else if (marker == brpc::AMF_MARKER_STRING) {
69+
uint16_t len;
70+
if (stream.cut_u16(&len) == 2 && len < 1024) {
71+
char tmp[1024];
72+
stream.cutn(tmp, len);
73+
}
74+
}
75+
}
76+
break;
77+
}
78+
}
79+
80+
return 0;
81+
}

test/fuzzing/fuzz_baidu_rpc.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "brpc/policy/baidu_rpc_protocol.h"
19+
#include "fuzz_common.h"
20+
21+
#define kMinInputLength 5
22+
#define kMaxInputLength 4096
23+
24+
extern "C" int
25+
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
26+
{
27+
if (size < kMinInputLength || size > kMaxInputLength){
28+
return 1;
29+
}
30+
31+
std::string input(reinterpret_cast<const char*>(data), size);
32+
butil::IOBuf buf;
33+
buf.append(input);
34+
35+
brpc::Socket* sock = get_fuzz_socket();
36+
brpc::policy::ParseRpcMessage(&buf, sock, false, NULL);
37+
return 0;
38+
}

test/fuzzing/fuzz_common.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#ifndef BRPC_TEST_FUZZING_FUZZ_COMMON_H
19+
#define BRPC_TEST_FUZZING_FUZZ_COMMON_H
20+
21+
#include "brpc/socket.h"
22+
#include "butil/endpoint.h"
23+
24+
// Create a valid Socket for use in fuzz harnesses that need a non-NULL Socket*.
25+
// Returns a raw Socket* that remains valid for the lifetime of the process
26+
// (held by the static SocketUniquePtr).
27+
inline brpc::Socket* get_fuzz_socket() {
28+
static brpc::SocketId sid = 0;
29+
static brpc::SocketUniquePtr sock_ptr;
30+
static bool initialized = false;
31+
32+
if (!initialized) {
33+
brpc::SocketOptions options;
34+
options.remote_side = butil::EndPoint(butil::IP_ANY, 7777);
35+
if (brpc::Socket::Create(options, &sid) == 0) {
36+
brpc::Socket::Address(sid, &sock_ptr);
37+
}
38+
initialized = true;
39+
}
40+
41+
return sock_ptr.get();
42+
}
43+
44+
#endif // BRPC_TEST_FUZZING_FUZZ_COMMON_H

test/fuzzing/fuzz_couchbase.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "brpc/policy/couchbase_protocol.h"
19+
#include "fuzz_common.h"
20+
21+
#define kMinInputLength 5
22+
#define kMaxInputLength 4096
23+
24+
extern "C" int
25+
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
26+
{
27+
if (size < kMinInputLength || size > kMaxInputLength){
28+
return 1;
29+
}
30+
31+
std::string input(reinterpret_cast<const char*>(data), size);
32+
butil::IOBuf buf;
33+
buf.append(input);
34+
35+
brpc::Socket* sock = get_fuzz_socket();
36+
brpc::policy::ParseCouchbaseMessage(&buf, sock, false, NULL);
37+
return 0;
38+
}

test/fuzzing/fuzz_esp.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717

1818
#include "brpc/policy/esp_protocol.h"
19+
#include "fuzz_common.h"
1920

2021
#define kMinInputLength 5
2122
#define kMaxInputLength 1024
@@ -32,7 +33,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
3233
butil::IOBuf buf;
3334
buf.append(input);
3435

35-
brpc::policy::ParseEspMessage(&buf, NULL, false, NULL);
36+
brpc::Socket* sock = get_fuzz_socket();
37+
brpc::policy::ParseEspMessage(&buf, sock, false, NULL);
3638

3739
return 0;
3840
}

test/fuzzing/fuzz_http_parser.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include <cstring>
19+
#include "brpc/details/http_parser.h"
20+
#include "brpc/http_method.h"
21+
22+
#define kMinInputLength 5
23+
#define kMaxInputLength 4096
24+
25+
static int on_url_cb(brpc::http_parser* p, const char* at, size_t length) { return 0; }
26+
static int on_header_field_cb(brpc::http_parser* p, const char* at, size_t length) { return 0; }
27+
static int on_header_value_cb(brpc::http_parser* p, const char* at, size_t length) { return 0; }
28+
static int on_body_cb(brpc::http_parser* p, const char* at, size_t length) { return 0; }
29+
static int on_message_begin_cb(brpc::http_parser* p) { return 0; }
30+
static int on_headers_complete_cb(brpc::http_parser* p) { return 0; }
31+
static int on_message_complete_cb(brpc::http_parser* p) { return 0; }
32+
33+
extern "C" int
34+
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
35+
{
36+
if (size < kMinInputLength || size > kMaxInputLength){
37+
return 1;
38+
}
39+
40+
// Use first byte to select mode
41+
uint8_t mode = data[0] % 4;
42+
const uint8_t *payload = data + 1;
43+
size_t payload_size = size - 1;
44+
45+
switch (mode) {
46+
case 0: {
47+
// Fuzz low-level HTTP request parsing
48+
brpc::http_parser parser;
49+
brpc::http_parser_init(&parser, brpc::HTTP_REQUEST);
50+
brpc::http_parser_settings settings;
51+
memset(&settings, 0, sizeof(settings));
52+
settings.on_url = on_url_cb;
53+
settings.on_header_field = on_header_field_cb;
54+
settings.on_header_value = on_header_value_cb;
55+
settings.on_body = on_body_cb;
56+
settings.on_message_begin = on_message_begin_cb;
57+
settings.on_headers_complete = on_headers_complete_cb;
58+
settings.on_message_complete = on_message_complete_cb;
59+
brpc::http_parser_execute(&parser, &settings,
60+
reinterpret_cast<const char*>(payload), payload_size);
61+
break;
62+
}
63+
case 1: {
64+
// Fuzz low-level HTTP response parsing
65+
brpc::http_parser parser;
66+
brpc::http_parser_init(&parser, brpc::HTTP_RESPONSE);
67+
brpc::http_parser_settings settings;
68+
memset(&settings, 0, sizeof(settings));
69+
settings.on_url = on_url_cb;
70+
settings.on_header_field = on_header_field_cb;
71+
settings.on_header_value = on_header_value_cb;
72+
settings.on_body = on_body_cb;
73+
settings.on_message_begin = on_message_begin_cb;
74+
settings.on_headers_complete = on_headers_complete_cb;
75+
settings.on_message_complete = on_message_complete_cb;
76+
brpc::http_parser_execute(&parser, &settings,
77+
reinterpret_cast<const char*>(payload), payload_size);
78+
break;
79+
}
80+
case 2: {
81+
// Fuzz URL parsing (not connect)
82+
brpc::http_parser_url u;
83+
brpc::http_parser_parse_url(reinterpret_cast<const char*>(payload),
84+
payload_size, 0, &u);
85+
break;
86+
}
87+
case 3: {
88+
// Fuzz URL parsing (connect mode)
89+
brpc::http_parser_url u;
90+
brpc::http_parser_parse_url(reinterpret_cast<const char*>(payload),
91+
payload_size, 1, &u);
92+
break;
93+
}
94+
}
95+
96+
return 0;
97+
}

test/fuzzing/fuzz_hulu.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717

1818
#include "brpc/policy/hulu_pbrpc_protocol.h"
19+
#include "fuzz_common.h"
1920

2021
#define kMinInputLength 5
2122
#define kMaxInputLength 1024
@@ -32,7 +33,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
3233
butil::IOBuf buf;
3334
buf.append(input);
3435

35-
brpc::policy::ParseHuluMessage(&buf, NULL, false, NULL);
36+
brpc::Socket* sock = get_fuzz_socket();
37+
brpc::policy::ParseHuluMessage(&buf, sock, false, NULL);
3638

3739
return 0;
3840
}

test/fuzzing/fuzz_memcache.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "brpc/policy/memcache_binary_protocol.h"
19+
#include "fuzz_common.h"
20+
21+
#define kMinInputLength 5
22+
#define kMaxInputLength 4096
23+
24+
extern "C" int
25+
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
26+
{
27+
if (size < kMinInputLength || size > kMaxInputLength){
28+
return 1;
29+
}
30+
31+
std::string input(reinterpret_cast<const char*>(data), size);
32+
butil::IOBuf buf;
33+
buf.append(input);
34+
35+
brpc::Socket* sock = get_fuzz_socket();
36+
brpc::policy::ParseMemcacheMessage(&buf, sock, false, NULL);
37+
return 0;
38+
}

0 commit comments

Comments
 (0)