Skip to content

Commit 9ec9ea5

Browse files
committed
Bug#35097487 fuzzer for client command codecs
The client-side protocol codec is currently tested with unit-, component- and integration tests which covers most happy cases. But not all edge-cases are covered. clang includes libfuzzer which allows writing fuzzers in a portable way. Change ------ Added fuzzers for all client side messages which is built if the compiler is clang. Change-Id: I43ddd2c57f97ca852577b67ca14cc85fd5132e3d
1 parent 8480b8c commit 9ec9ea5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1742
-3
lines changed

router/cmake/fuzzer.cmake

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,8 @@ FUNCTION(LIBFUZZER_ADD_TEST TARGET)
186186
)
187187
ENDIF()
188188

189-
# use cmake -E env to set the LLVM_PROFILE_FILE in a portable way
190-
ADD_TEST(${TARGET}
191-
${TARGET}
189+
ADD_TEST(NAME ${TARGET}
190+
COMMAND ${TARGET}
192191
-max_total_time=${ARG_MAX_TOTAL_TIME} -timeout=${ARG_TIMEOUT}
193192
-artifact_prefix=${BINARY_ARTIFACT_DIR}/
194193
${BINARY_CORPUS_DIR}

router/src/mysql_protocol/tests/CMakeLists.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,47 @@ FOREACH(test_file
5252
INCLUDE_DIRS ../include/
5353
LIB_DEPENDS harness_stdx)
5454
ENDFOREACH()
55+
56+
IF(LIBFUZZER_COMPILE_FLAGS)
57+
FOREACH(CMD client_greeting
58+
quit
59+
init_schema
60+
query
61+
list_fields
62+
# create_db
63+
# drop_db
64+
reload
65+
# shutdown
66+
statistics
67+
# processinfo
68+
# connect
69+
# debug
70+
ping
71+
# time
72+
# delayedinsert
73+
change_user
74+
binlog_dump
75+
# table_dump
76+
# connect_out
77+
register_replica
78+
stmt_prepare
79+
stmt_execute
80+
stmt_param_append_data
81+
stmt_close
82+
stmt_reset
83+
set_option
84+
stmt_fetch
85+
# daemon
86+
binlog_dump_gtid
87+
reset_connection
88+
clone)
89+
MYSQL_ADD_EXECUTABLE(routertest_fuzz_mysql_protocol_${CMD}
90+
fuzz_${CMD}.cc
91+
COMPONENT Router
92+
LINK_LIBRARIES mysql_protocol
93+
SKIP_INSTALL
94+
)
95+
LIBFUZZER_ADD_TEST(routertest_fuzz_mysql_protocol_${CMD}
96+
INITIAL_CORPUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/corpus/${CMD})
97+
ENDFOREACH()
98+
ENDIF()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright (c) 2023, Oracle and/or its affiliates.
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License, version 2.0,
6+
as published by the Free Software Foundation.
7+
8+
This program is also distributed with certain software (including
9+
but not limited to OpenSSL) that is licensed under separate terms,
10+
as designated in a particular file or component or in included license
11+
documentation. The authors of MySQL hereby grant you an additional
12+
permission to link the program and your derivative works with the
13+
separately licensed software that they have included with MySQL.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
*/
24+
25+
#include "mysqlrouter/classic_protocol_codec_message.h"
26+
#include "mysqlrouter/classic_protocol_message.h"
27+
28+
#include <iostream>
29+
30+
#include "hexify.h"
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
33+
auto data = net::const_buffer(Data, Size);
34+
35+
if (data.size() < 4) return 0;
36+
37+
// byte 0-3: caps
38+
// rest : msg
39+
40+
const uint32_t caps = *reinterpret_cast<const uint32_t *>(data.data());
41+
data += 4;
42+
43+
using msg_type = classic_protocol::borrowed::message::client::BinlogDump;
44+
45+
auto decode_res = classic_protocol::Codec<msg_type>::decode(data, caps);
46+
if (decode_res) {
47+
// if it decode, can we encode it again?
48+
49+
std::vector<uint8_t> buf;
50+
auto encode_res = classic_protocol::encode(decode_res->second, caps,
51+
net::dynamic_buffer(buf));
52+
53+
if (!encode_res) {
54+
std::cerr << "Encoding encoded msg failed: " << encode_res.error()
55+
<< "\n";
56+
abort();
57+
}
58+
59+
// ... and decode again?
60+
auto decode_again_res =
61+
classic_protocol::Codec<msg_type>::decode(net::buffer(buf), caps);
62+
63+
if (!decode_again_res) {
64+
std::cerr << "Decoding encoded msg failed: " << decode_again_res.error()
65+
<< "\n"
66+
<< "Input:\n"
67+
<< mysql_harness::hexify(buf) << "\n"
68+
<< "(original input):\n"
69+
<< mysql_harness::hexify(data) << "\n";
70+
71+
abort();
72+
}
73+
}
74+
75+
return 0;
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright (c) 2023, Oracle and/or its affiliates.
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License, version 2.0,
6+
as published by the Free Software Foundation.
7+
8+
This program is also distributed with certain software (including
9+
but not limited to OpenSSL) that is licensed under separate terms,
10+
as designated in a particular file or component or in included license
11+
documentation. The authors of MySQL hereby grant you an additional
12+
permission to link the program and your derivative works with the
13+
separately licensed software that they have included with MySQL.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
*/
24+
25+
#include "mysqlrouter/classic_protocol_codec_message.h"
26+
#include "mysqlrouter/classic_protocol_message.h"
27+
28+
#include <iostream>
29+
30+
#include "hexify.h"
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
33+
auto data = net::const_buffer(Data, Size);
34+
35+
if (data.size() < 4) return 0;
36+
37+
// byte 0-3: caps
38+
// rest : msg
39+
40+
const uint32_t caps = *reinterpret_cast<const uint32_t *>(data.data());
41+
data += 4;
42+
43+
using msg_type = classic_protocol::borrowed::message::client::BinlogDumpGtid;
44+
45+
auto decode_res = classic_protocol::Codec<msg_type>::decode(data, caps);
46+
if (decode_res) {
47+
// if it decode, can we encode it again?
48+
49+
std::vector<uint8_t> buf;
50+
auto encode_res = classic_protocol::encode(decode_res->second, caps,
51+
net::dynamic_buffer(buf));
52+
53+
if (!encode_res) {
54+
std::cerr << "Encoding encoded msg failed: " << encode_res.error()
55+
<< "\n";
56+
abort();
57+
}
58+
59+
// ... and decode again?
60+
auto decode_again_res =
61+
classic_protocol::Codec<msg_type>::decode(net::buffer(buf), caps);
62+
63+
if (!decode_again_res) {
64+
std::cerr << "Decoding encoded msg failed: " << decode_again_res.error()
65+
<< "\n"
66+
<< "Input:\n"
67+
<< mysql_harness::hexify(buf) << "\n"
68+
<< "(original input):\n"
69+
<< mysql_harness::hexify(data) << "\n";
70+
71+
abort();
72+
}
73+
}
74+
75+
return 0;
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright (c) 2023, Oracle and/or its affiliates.
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License, version 2.0,
6+
as published by the Free Software Foundation.
7+
8+
This program is also distributed with certain software (including
9+
but not limited to OpenSSL) that is licensed under separate terms,
10+
as designated in a particular file or component or in included license
11+
documentation. The authors of MySQL hereby grant you an additional
12+
permission to link the program and your derivative works with the
13+
separately licensed software that they have included with MySQL.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
*/
24+
25+
#include "mysqlrouter/classic_protocol_codec_message.h"
26+
#include "mysqlrouter/classic_protocol_message.h"
27+
28+
#include <iostream>
29+
30+
#include "hexify.h"
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
33+
auto data = net::const_buffer(Data, Size);
34+
35+
if (data.size() < 4) return 0;
36+
37+
// byte 0-3: caps
38+
// rest : msg
39+
40+
const uint32_t caps = *reinterpret_cast<const uint32_t *>(data.data());
41+
data += 4;
42+
43+
using msg_type = classic_protocol::borrowed::message::client::ChangeUser;
44+
45+
auto decode_res = classic_protocol::Codec<msg_type>::decode(data, caps);
46+
if (decode_res) {
47+
// if it decode, can we encode it again?
48+
49+
std::vector<uint8_t> buf;
50+
auto encode_res = classic_protocol::encode(decode_res->second, caps,
51+
net::dynamic_buffer(buf));
52+
53+
if (!encode_res) {
54+
std::cerr << "Encoding encoded msg failed: " << encode_res.error()
55+
<< "\n";
56+
abort();
57+
}
58+
59+
// ... and decode again?
60+
auto decode_again_res =
61+
classic_protocol::Codec<msg_type>::decode(net::buffer(buf), caps);
62+
63+
if (!decode_again_res) {
64+
std::cerr << "Decoding encoded msg failed: " << decode_again_res.error()
65+
<< "\n"
66+
<< "Input:\n"
67+
<< mysql_harness::hexify(buf) << "\n"
68+
<< "(original input):\n"
69+
<< mysql_harness::hexify(data) << "\n";
70+
71+
abort();
72+
}
73+
}
74+
75+
return 0;
76+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright (c) 2023, Oracle and/or its affiliates.
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License, version 2.0,
6+
as published by the Free Software Foundation.
7+
8+
This program is also distributed with certain software (including
9+
but not limited to OpenSSL) that is licensed under separate terms,
10+
as designated in a particular file or component or in included license
11+
documentation. The authors of MySQL hereby grant you an additional
12+
permission to link the program and your derivative works with the
13+
separately licensed software that they have included with MySQL.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
*/
24+
25+
#include "mysqlrouter/classic_protocol_codec_message.h"
26+
#include "mysqlrouter/classic_protocol_message.h"
27+
28+
#include <iostream>
29+
30+
#include "hexify.h"
31+
32+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
33+
auto data = net::const_buffer(Data, Size);
34+
35+
if (data.size() < 4) return 0;
36+
37+
// byte 0-3: caps
38+
// rest : msg
39+
40+
const uint32_t caps = *reinterpret_cast<const uint32_t *>(data.data());
41+
data += 4;
42+
43+
using msg_type = classic_protocol::borrowed::message::client::Greeting;
44+
45+
auto decode_res = classic_protocol::Codec<msg_type>::decode(data, caps);
46+
if (decode_res) {
47+
// if it decode, can we encode it again?
48+
49+
std::vector<uint8_t> buf;
50+
auto encode_res = classic_protocol::encode(decode_res->second, caps,
51+
net::dynamic_buffer(buf));
52+
53+
if (!encode_res) {
54+
std::cerr << "Encoding encoded msg failed: " << encode_res.error()
55+
<< "\n";
56+
abort();
57+
}
58+
59+
// ... and decode again?
60+
auto decode_again_res =
61+
classic_protocol::Codec<msg_type>::decode(net::buffer(buf), caps);
62+
63+
if (!decode_again_res) {
64+
std::cerr << "Decoding encoded msg failed: " << decode_again_res.error()
65+
<< "\n"
66+
<< "Input:\n"
67+
<< mysql_harness::hexify(buf) << "\n"
68+
<< "(original input):\n"
69+
<< mysql_harness::hexify(data) << "\n";
70+
71+
abort();
72+
}
73+
}
74+
75+
return 0;
76+
}

0 commit comments

Comments
 (0)