Skip to content

Commit fd094fe

Browse files
authored
Merge pull request #4032 from bluca/fuzzers
Problem: no fuzzing coverage for ZMQ_STREAM
2 parents cbce0cb + e708623 commit fd094fe

3 files changed

Lines changed: 277 additions & 0 deletions

File tree

Makefile.am

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,8 @@ fuzzer_apps = tests/test_bind_null_fuzzer \
11281128
tests/test_connect_null_fuzzer \
11291129
tests/test_bind_fuzzer \
11301130
tests/test_connect_fuzzer \
1131+
tests/test_bind_stream_fuzzer \
1132+
tests/test_connect_stream_fuzzer \
11311133
tests/test_socket_options_fuzzer
11321134

11331135
tests_test_bind_null_fuzzer_DEPENDENCIES = src/libzmq.la
@@ -1170,6 +1172,22 @@ tests_test_socket_options_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB}
11701172
tests_test_socket_options_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
11711173
tests_test_socket_options_fuzzer_CXXFLAGS = -std=c++11
11721174

1175+
tests_test_bind_stream_fuzzer_DEPENDENCIES = src/libzmq.la
1176+
tests_test_bind_stream_fuzzer_SOURCES = tests/test_bind_stream_fuzzer.cpp
1177+
tests_test_bind_stream_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
1178+
$(top_builddir)/src/.libs/libzmq.a \
1179+
${src_libzmq_la_LIBADD}
1180+
tests_test_bind_stream_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
1181+
tests_test_bind_stream_fuzzer_CXXFLAGS = -std=c++11
1182+
1183+
tests_test_connect_stream_fuzzer_DEPENDENCIES = src/libzmq.la
1184+
tests_test_connect_stream_fuzzer_SOURCES = tests/test_connect_stream_fuzzer.cpp
1185+
tests_test_connect_stream_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
1186+
$(top_builddir)/src/.libs/libzmq.a \
1187+
${src_libzmq_la_LIBADD}
1188+
tests_test_connect_stream_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
1189+
tests_test_connect_stream_fuzzer_CXXFLAGS = -std=c++11
1190+
11731191
if HAVE_CURVE
11741192
fuzzer_apps += tests/test_bind_curve_fuzzer \
11751193
tests/test_connect_curve_fuzzer \
@@ -1228,6 +1246,8 @@ test_apps += tests/test_bind_null_fuzzer \
12281246
tests/test_connect_null_fuzzer \
12291247
tests/test_bind_fuzzer \
12301248
tests/test_connect_fuzzer \
1249+
tests/test_bind_stream_fuzzer \
1250+
tests/test_connect_stream_fuzzer \
12311251
tests/test_socket_options_fuzzer
12321252

12331253
tests_test_bind_null_fuzzer_SOURCES = tests/test_bind_null_fuzzer.cpp
@@ -1250,6 +1270,14 @@ tests_test_socket_options_fuzzer_SOURCES = tests/test_socket_options_fuzzer.cpp
12501270
tests_test_socket_options_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
12511271
tests_test_socket_options_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
12521272

1273+
tests_test_bind_stream_fuzzer_SOURCES = tests/test_bind_stream_fuzzer.cpp
1274+
tests_test_bind_stream_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
1275+
tests_test_bind_stream_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
1276+
1277+
tests_test_connect_stream_fuzzer_SOURCES = tests/test_connect_stream_fuzzer.cpp
1278+
tests_test_connect_stream_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
1279+
tests_test_connect_stream_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
1280+
12531281
if HAVE_CURVE
12541282
test_apps += tests/test_bind_curve_fuzzer \
12551283
tests/test_connect_curve_fuzzer \

tests/test_bind_stream_fuzzer.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
Copyright (c) 2020 Contributors as noted in the AUTHORS file
3+
4+
This file is part of libzmq, the ZeroMQ core engine in C++.
5+
6+
libzmq is free software; you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
As a special exception, the Contributors give you permission to link
12+
this library with independent modules to produce an executable,
13+
regardless of the license terms of these independent modules, and to
14+
copy and distribute the resulting executable under terms of your choice,
15+
provided that you also meet, for each linked independent module, the
16+
terms and conditions of the license of that module. An independent
17+
module is a module which is not derived from or based on this library.
18+
If you modify this library, you must extend this exception to your
19+
version of the library.
20+
21+
libzmq is distributed in the hope that it will be useful, but WITHOUT
22+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24+
License for more details.
25+
26+
You should have received a copy of the GNU Lesser General Public License
27+
along with this program. If not, see <http://www.gnu.org/licenses/>.
28+
*/
29+
30+
#ifdef ZMQ_USE_FUZZING_ENGINE
31+
#include <fuzzer/FuzzedDataProvider.h>
32+
#endif
33+
34+
#include "testutil.hpp"
35+
#include "testutil_unity.hpp"
36+
37+
// Test that the ZMTP engine handles invalid handshake when binding
38+
// https://rfc.zeromq.org/spec/37/
39+
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
40+
{
41+
setup_test_context ();
42+
char my_endpoint[MAX_SOCKET_STRING];
43+
void *server = test_context_socket (ZMQ_STREAM);
44+
// As per API by default there's no limit to the size of a message,
45+
// but the sanitizer allocator will barf over a gig or so
46+
int64_t max_msg_size = 64 * 1024 * 1024;
47+
TEST_ASSERT_SUCCESS_ERRNO (
48+
zmq_setsockopt (server, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
49+
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
50+
fd_t client = connect_socket (my_endpoint);
51+
52+
// If there is not enough data for a full greeting, just send what we can
53+
// Otherwise send greeting first, as expected by the protocol
54+
uint8_t buf[64];
55+
if (size >= 64) {
56+
send (client, (void *) data, 64, MSG_NOSIGNAL);
57+
data += 64;
58+
size -= 64;
59+
}
60+
recv (client, buf, 64, MSG_DONTWAIT);
61+
msleep (250);
62+
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
63+
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
64+
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
65+
msleep (250);
66+
67+
zmq_msg_t msg;
68+
zmq_msg_init (&msg);
69+
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
70+
zmq_msg_close (&msg);
71+
zmq_msg_init (&msg);
72+
}
73+
74+
void *client_good = test_context_socket (ZMQ_DEALER);
75+
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_good, my_endpoint));
76+
77+
TEST_ASSERT_EQUAL_INT (6, zmq_send_const (client_good, "HELLO", 6, 0));
78+
zmq_msg_t routing_id;
79+
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&routing_id));
80+
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, server, 0));
81+
TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));
82+
char const *peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
83+
zmq_msg_close (&routing_id);
84+
TEST_ASSERT_NOT_NULL (peer_address);
85+
TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);
86+
TEST_ASSERT_EQUAL_INT (
87+
0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (server, buf, 64, 0)));
88+
zmq_msg_init (&msg);
89+
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
90+
zmq_msg_close (&msg);
91+
zmq_msg_init (&msg);
92+
}
93+
94+
close (client);
95+
test_context_socket_close_zero_linger (client_good);
96+
test_context_socket_close_zero_linger (server);
97+
teardown_test_context ();
98+
99+
return 0;
100+
}
101+
102+
#ifndef ZMQ_USE_FUZZING_ENGINE
103+
void test_bind_stream_fuzzer ()
104+
{
105+
uint8_t **data;
106+
size_t *len, num_cases = 0;
107+
if (fuzzer_corpus_encode (
108+
"tests/libzmq-fuzz-corpora/test_bind_stream_fuzzer_seed_corpus",
109+
&data, &len, &num_cases)
110+
!= 0)
111+
exit (77);
112+
113+
while (num_cases-- > 0) {
114+
TEST_ASSERT_SUCCESS_ERRNO (
115+
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
116+
free (data[num_cases]);
117+
}
118+
119+
free (data);
120+
free (len);
121+
}
122+
123+
int main (int argc, char **argv)
124+
{
125+
setup_test_environment ();
126+
127+
UNITY_BEGIN ();
128+
RUN_TEST (test_bind_stream_fuzzer);
129+
130+
return UNITY_END ();
131+
}
132+
#endif
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
Copyright (c) 2020 Contributors as noted in the AUTHORS file
3+
4+
This file is part of libzmq, the ZeroMQ core engine in C++.
5+
6+
libzmq is free software; you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
As a special exception, the Contributors give you permission to link
12+
this library with independent modules to produce an executable,
13+
regardless of the license terms of these independent modules, and to
14+
copy and distribute the resulting executable under terms of your choice,
15+
provided that you also meet, for each linked independent module, the
16+
terms and conditions of the license of that module. An independent
17+
module is a module which is not derived from or based on this library.
18+
If you modify this library, you must extend this exception to your
19+
version of the library.
20+
21+
libzmq is distributed in the hope that it will be useful, but WITHOUT
22+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24+
License for more details.
25+
26+
You should have received a copy of the GNU Lesser General Public License
27+
along with this program. If not, see <http://www.gnu.org/licenses/>.
28+
*/
29+
30+
#ifdef ZMQ_USE_FUZZING_ENGINE
31+
#include <fuzzer/FuzzedDataProvider.h>
32+
#endif
33+
34+
#include "testutil.hpp"
35+
#include "testutil_unity.hpp"
36+
37+
// Test that the ZMTP engine handles invalid handshake when connecting
38+
// https://rfc.zeromq.org/spec/37/
39+
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
40+
{
41+
setup_test_context ();
42+
char my_endpoint[MAX_SOCKET_STRING];
43+
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
44+
45+
void *client = test_context_socket (ZMQ_STREAM);
46+
// As per API by default there's no limit to the size of a message,
47+
// but the sanitizer allocator will barf over a gig or so
48+
int64_t max_msg_size = 64 * 1024 * 1024;
49+
TEST_ASSERT_SUCCESS_ERRNO (
50+
zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
51+
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
52+
53+
fd_t server_accept =
54+
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
55+
56+
// If there is not enough data for a full greeting, just send what we can
57+
// Otherwise send greeting first, as expected by the protocol
58+
uint8_t buf[64];
59+
if (size >= 64) {
60+
send (server_accept, (void *) data, 64, MSG_NOSIGNAL);
61+
data += 64;
62+
size -= 64;
63+
}
64+
recv (server_accept, buf, 64, MSG_DONTWAIT);
65+
msleep (250);
66+
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
67+
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
68+
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
69+
msleep (250);
70+
71+
zmq_msg_t msg;
72+
zmq_msg_init (&msg);
73+
while (-1 != zmq_msg_recv (&msg, client, ZMQ_DONTWAIT)) {
74+
zmq_msg_close (&msg);
75+
zmq_msg_init (&msg);
76+
}
77+
78+
close (server_accept);
79+
close (server);
80+
81+
test_context_socket_close_zero_linger (client);
82+
teardown_test_context ();
83+
84+
return 0;
85+
}
86+
87+
#ifndef ZMQ_USE_FUZZING_ENGINE
88+
void test_connect_null_fuzzer ()
89+
{
90+
uint8_t **data;
91+
size_t *len, num_cases = 0;
92+
if (fuzzer_corpus_encode (
93+
"tests/libzmq-fuzz-corpora/test_connect_null_fuzzer_seed_corpus",
94+
&data, &len, &num_cases)
95+
!= 0)
96+
exit (77);
97+
98+
while (num_cases-- > 0) {
99+
TEST_ASSERT_SUCCESS_ERRNO (
100+
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
101+
free (data[num_cases]);
102+
}
103+
104+
free (data);
105+
free (len);
106+
}
107+
108+
int main (int argc, char **argv)
109+
{
110+
setup_test_environment ();
111+
112+
UNITY_BEGIN ();
113+
RUN_TEST (test_connect_null_fuzzer);
114+
115+
return UNITY_END ();
116+
}
117+
#endif

0 commit comments

Comments
 (0)