|
| 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 |
0 commit comments