1 /*
2 Copyright (c) 2007-2019 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 #include "testutil.hpp"
30 #include "testutil_unity.hpp"
31
32 #include <stdarg.h>
33 #include <string.h>
34
35 #if defined _WIN32
36 #include "../src/windows.hpp"
37 #if defined _MSC_VER
38 #if defined ZMQ_HAVE_IPC
39 #include <direct.h>
40 #include <afunix.h>
41 #endif
42 #include <crtdbg.h>
43 #pragma warning(disable : 4996)
44 // iphlpapi is needed for if_nametoindex (not on Windows XP)
45 #if _WIN32_WINNT > _WIN32_WINNT_WINXP
46 #pragma comment(lib, "iphlpapi")
47 #endif
48 #endif
49 #else
50 #include <pthread.h>
51 #include <unistd.h>
52 #include <signal.h>
53 #include <stdlib.h>
54 #include <grp.h>
55 #include <sys/wait.h>
56 #include <sys/socket.h>
57 #include <sys/types.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <net/if.h>
61 #include <netdb.h>
62 #include <sys/un.h>
63 #include <dirent.h>
64 #if defined(ZMQ_HAVE_AIX)
65 #include <sys/types.h>
66 #include <sys/socketvar.h>
67 #endif
68 #endif
69
70 #ifndef PATH_MAX
71 #define PATH_MAX 1024
72 #endif
73
74 const char *SEQ_END = (const char *) 1;
75
76 const char bounce_content[] = "12345678ABCDEFGH12345678abcdefgh";
77
send_bounce_msg(void * socket_)78 static void send_bounce_msg (void *socket_)
79 {
80 send_string_expect_success (socket_, bounce_content, ZMQ_SNDMORE);
81 send_string_expect_success (socket_, bounce_content, 0);
82 }
83
recv_bounce_msg(void * socket_)84 static void recv_bounce_msg (void *socket_)
85 {
86 recv_string_expect_success (socket_, bounce_content, 0);
87 int rcvmore;
88 size_t sz = sizeof (rcvmore);
89 TEST_ASSERT_SUCCESS_ERRNO (
90 zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz));
91 TEST_ASSERT_TRUE (rcvmore);
92 recv_string_expect_success (socket_, bounce_content, 0);
93 TEST_ASSERT_SUCCESS_ERRNO (
94 zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz));
95 TEST_ASSERT_FALSE (rcvmore);
96 }
97
bounce(void * server_,void * client_)98 void bounce (void *server_, void *client_)
99 {
100 // Send message from client to server
101 send_bounce_msg (client_);
102
103 // Receive message at server side and
104 // check that message is still the same
105 recv_bounce_msg (server_);
106
107 // Send two parts back to client
108 send_bounce_msg (server_);
109
110 // Receive the two parts at the client side
111 recv_bounce_msg (client_);
112 }
113
send_bounce_msg_may_fail(void * socket_)114 static void send_bounce_msg_may_fail (void *socket_)
115 {
116 int timeout = 250;
117 TEST_ASSERT_SUCCESS_ERRNO (
118 zmq_setsockopt (socket_, ZMQ_SNDTIMEO, &timeout, sizeof (int)));
119 int rc = zmq_send (socket_, bounce_content, 32, ZMQ_SNDMORE);
120 TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
121 rc = zmq_send (socket_, bounce_content, 32, 0);
122 TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
123 }
124
recv_bounce_msg_fail(void * socket_)125 static void recv_bounce_msg_fail (void *socket_)
126 {
127 int timeout = 250;
128 char buffer[32];
129 TEST_ASSERT_SUCCESS_ERRNO (
130 zmq_setsockopt (socket_, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
131 TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (socket_, buffer, 32, 0));
132 }
133
expect_bounce_fail(void * server_,void * client_)134 void expect_bounce_fail (void *server_, void *client_)
135 {
136 // Send message from client to server
137 send_bounce_msg_may_fail (client_);
138
139 // Receive message at server side (should not succeed)
140 recv_bounce_msg_fail (server_);
141
142 // Send message from server to client to test other direction
143 // If connection failed, send may block, without a timeout
144 send_bounce_msg_may_fail (server_);
145
146 // Receive message at client side (should not succeed)
147 recv_bounce_msg_fail (client_);
148 }
149
s_recv(void * socket_)150 char *s_recv (void *socket_)
151 {
152 char buffer[256];
153 int size = zmq_recv (socket_, buffer, 255, 0);
154 if (size == -1)
155 return NULL;
156 if (size > 255)
157 size = 255;
158 buffer[size] = 0;
159 return strdup (buffer);
160 }
161
s_send_seq(void * socket_,...)162 void s_send_seq (void *socket_, ...)
163 {
164 va_list ap;
165 va_start (ap, socket_);
166 const char *data = va_arg (ap, const char *);
167 while (true) {
168 const char *prev = data;
169 data = va_arg (ap, const char *);
170 bool end = data == SEQ_END;
171
172 if (!prev) {
173 TEST_ASSERT_SUCCESS_ERRNO (
174 zmq_send (socket_, 0, 0, end ? 0 : ZMQ_SNDMORE));
175 } else {
176 TEST_ASSERT_SUCCESS_ERRNO (zmq_send (
177 socket_, prev, strlen (prev) + 1, end ? 0 : ZMQ_SNDMORE));
178 }
179 if (end)
180 break;
181 }
182 va_end (ap);
183 }
184
s_recv_seq(void * socket_,...)185 void s_recv_seq (void *socket_, ...)
186 {
187 zmq_msg_t msg;
188 zmq_msg_init (&msg);
189
190 int more;
191 size_t more_size = sizeof (more);
192
193 va_list ap;
194 va_start (ap, socket_);
195 const char *data = va_arg (ap, const char *);
196
197 while (true) {
198 TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, socket_, 0));
199
200 if (!data)
201 TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg));
202 else
203 TEST_ASSERT_EQUAL_STRING (data, (const char *) zmq_msg_data (&msg));
204
205 data = va_arg (ap, const char *);
206 bool end = data == SEQ_END;
207
208 TEST_ASSERT_SUCCESS_ERRNO (
209 zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size));
210
211 TEST_ASSERT_TRUE (!more == end);
212 if (end)
213 break;
214 }
215 va_end (ap);
216
217 zmq_msg_close (&msg);
218 }
219
close_zero_linger(void * socket_)220 void close_zero_linger (void *socket_)
221 {
222 int linger = 0;
223 int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
224 TEST_ASSERT_TRUE (rc == 0 || errno == ETERM);
225 TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket_));
226 }
227
setup_test_environment(int timeout_seconds_)228 void setup_test_environment (int timeout_seconds_)
229 {
230 #if defined _WIN32
231 #if defined _MSC_VER
232 _set_abort_behavior (0, _WRITE_ABORT_MSG);
233 _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
234 _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
235 #endif
236 #else
237 #if defined ZMQ_HAVE_CYGWIN
238 // abort test after 121 seconds
239 alarm (121);
240 #else
241 #if !defined ZMQ_DISABLE_TEST_TIMEOUT
242 // abort test after timeout_seconds_ seconds
243 alarm (timeout_seconds_);
244 #endif
245 #endif
246 #endif
247 #if defined __MVS__
248 // z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
249 // workaround for no SO_NOGSIGPIPE socket option.
250 signal (SIGPIPE, SIG_IGN);
251 #endif
252 }
253
msleep(int milliseconds_)254 void msleep (int milliseconds_)
255 {
256 #ifdef ZMQ_HAVE_WINDOWS
257 Sleep (milliseconds_);
258 #else
259 usleep (static_cast<useconds_t> (milliseconds_) * 1000);
260 #endif
261 }
262
is_ipv6_available()263 int is_ipv6_available ()
264 {
265 #if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
266 return 0;
267 #else
268 int rc, ipv6 = 1;
269 struct sockaddr_in6 test_addr;
270
271 memset (&test_addr, 0, sizeof (test_addr));
272 test_addr.sin6_family = AF_INET6;
273 inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr));
274
275 fd_t fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
276 if (fd == retired_fd)
277 ipv6 = 0;
278 else {
279 #ifdef ZMQ_HAVE_WINDOWS
280 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &ipv6,
281 sizeof (int));
282 rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6,
283 sizeof (int));
284 if (rc == SOCKET_ERROR)
285 ipv6 = 0;
286 else {
287 rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
288 if (rc == SOCKET_ERROR)
289 ipv6 = 0;
290 }
291 #else
292 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof (int));
293 rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof (int));
294 if (rc != 0)
295 ipv6 = 0;
296 else {
297 rc = bind (fd, reinterpret_cast<struct sockaddr *> (&test_addr),
298 sizeof (test_addr));
299 if (rc != 0)
300 ipv6 = 0;
301 }
302 #endif
303 close (fd);
304 }
305
306 return ipv6;
307 #endif // _WIN32_WINNT < 0x0600
308 }
309
is_tipc_available()310 int is_tipc_available ()
311 {
312 #ifndef ZMQ_HAVE_TIPC
313 return 0;
314 #else
315 int tipc = 0;
316
317 void *ctx = zmq_init (1);
318 TEST_ASSERT_NOT_NULL (ctx);
319 void *rep = zmq_socket (ctx, ZMQ_REP);
320 TEST_ASSERT_NOT_NULL (rep);
321 tipc = zmq_bind (rep, "tipc://{5560,0,0}");
322
323 zmq_close (rep);
324 zmq_ctx_term (ctx);
325
326 return tipc == 0;
327 #endif // ZMQ_HAVE_TIPC
328 }
329
test_inet_pton(int af_,const char * src_,void * dst_)330 int test_inet_pton (int af_, const char *src_, void *dst_)
331 {
332 #if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
333 if (af_ == AF_INET) {
334 struct in_addr *ip4addr = (struct in_addr *) dst_;
335
336 ip4addr->s_addr = inet_addr (src_);
337
338 // INADDR_NONE is -1 which is also a valid representation for IP
339 // 255.255.255.255
340 if (ip4addr->s_addr == INADDR_NONE
341 && strcmp (src_, "255.255.255.255") != 0) {
342 return 0;
343 }
344
345 // Success
346 return 1;
347 } else {
348 // Not supported.
349 return 0;
350 }
351 #else
352 return inet_pton (af_, src_, dst_);
353 #endif
354 }
355
bind_bsd_socket(int socket_)356 sockaddr_in bind_bsd_socket (int socket_)
357 {
358 struct sockaddr_in saddr;
359 memset (&saddr, 0, sizeof (saddr));
360 saddr.sin_family = AF_INET;
361 saddr.sin_addr.s_addr = INADDR_ANY;
362 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
363 saddr.sin_port = 0;
364 #else
365 saddr.sin_port = htons (PORT_6);
366 #endif
367
368 TEST_ASSERT_SUCCESS_RAW_ERRNO (
369 bind (socket_, (struct sockaddr *) &saddr, sizeof (saddr)));
370
371 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
372 socklen_t saddr_len = sizeof (saddr);
373 TEST_ASSERT_SUCCESS_RAW_ERRNO (
374 getsockname (socket_, (struct sockaddr *) &saddr, &saddr_len));
375 #endif
376
377 return saddr;
378 }
379
connect_socket(const char * endpoint_,const int af_,const int protocol_)380 fd_t connect_socket (const char *endpoint_, const int af_, const int protocol_)
381 {
382 struct sockaddr_storage addr;
383 // OSX is very opinionated and wants the size to match the AF family type
384 socklen_t addr_len;
385 const fd_t s_pre = socket (af_, SOCK_STREAM,
386 protocol_ == IPPROTO_UDP
387 ? IPPROTO_UDP
388 : protocol_ == IPPROTO_TCP ? IPPROTO_TCP : 0);
389 TEST_ASSERT_NOT_EQUAL (-1, s_pre);
390
391 if (af_ == AF_INET || af_ == AF_INET6) {
392 const char *port = strrchr (endpoint_, ':') + 1;
393 char address[MAX_SOCKET_STRING];
394 // getaddrinfo does not like [x:y::z]
395 if (*strchr (endpoint_, '/') + 2 == '[') {
396 strcpy (address, strchr (endpoint_, '[') + 1);
397 address[strlen (address) - strlen (port) - 2] = '\0';
398 } else {
399 strcpy (address, strchr (endpoint_, '/') + 2);
400 address[strlen (address) - strlen (port) - 1] = '\0';
401 }
402
403 struct addrinfo *in, hint;
404 memset (&hint, 0, sizeof (struct addrinfo));
405 hint.ai_flags = AI_NUMERICSERV;
406 hint.ai_family = af_;
407 hint.ai_socktype = protocol_ == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
408 hint.ai_protocol = protocol_ == IPPROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
409
410 TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (
411 getaddrinfo (address, port, &hint, &in));
412 TEST_ASSERT_NOT_NULL (in);
413 memcpy (&addr, in->ai_addr, in->ai_addrlen);
414 addr_len = (socklen_t) in->ai_addrlen;
415 freeaddrinfo (in);
416 } else {
417 #if defined(ZMQ_HAVE_IPC)
418 // Cannot cast addr as gcc 4.4 will fail with strict aliasing errors
419 (*(struct sockaddr_un *) &addr).sun_family = AF_UNIX;
420 strcpy ((*(struct sockaddr_un *) &addr).sun_path, endpoint_);
421 addr_len = sizeof (struct sockaddr_un);
422 #else
423 return retired_fd;
424 #endif
425 }
426
427 TEST_ASSERT_SUCCESS_RAW_ERRNO (
428 connect (s_pre, (struct sockaddr *) &addr, addr_len));
429
430 return s_pre;
431 }
432
bind_socket_resolve_port(const char * address_,const char * port_,char * my_endpoint_,const int af_,const int protocol_)433 fd_t bind_socket_resolve_port (const char *address_,
434 const char *port_,
435 char *my_endpoint_,
436 const int af_,
437 const int protocol_)
438 {
439 struct sockaddr_storage addr;
440 // OSX is very opinionated and wants the size to match the AF family type
441 socklen_t addr_len;
442 const fd_t s_pre = socket (af_, SOCK_STREAM,
443 protocol_ == IPPROTO_UDP
444 ? IPPROTO_UDP
445 : protocol_ == IPPROTO_TCP ? IPPROTO_TCP : 0);
446 TEST_ASSERT_NOT_EQUAL (-1, s_pre);
447
448 if (af_ == AF_INET || af_ == AF_INET6) {
449 #ifdef ZMQ_HAVE_WINDOWS
450 const char flag = '\1';
451 #elif defined ZMQ_HAVE_VXWORKS
452 char flag = '\1';
453 #else
454 int flag = 1;
455 #endif
456 struct addrinfo *in, hint;
457 memset (&hint, 0, sizeof (struct addrinfo));
458 hint.ai_flags = AI_NUMERICSERV;
459 hint.ai_family = af_;
460 hint.ai_socktype = protocol_ == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
461 hint.ai_protocol = protocol_ == IPPROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
462
463 TEST_ASSERT_SUCCESS_RAW_ERRNO (
464 setsockopt (s_pre, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)));
465 TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (
466 getaddrinfo (address_, port_, &hint, &in));
467 TEST_ASSERT_NOT_NULL (in);
468 memcpy (&addr, in->ai_addr, in->ai_addrlen);
469 addr_len = (socklen_t) in->ai_addrlen;
470 freeaddrinfo (in);
471 } else {
472 #if defined(ZMQ_HAVE_IPC)
473 // Cannot cast addr as gcc 4.4 will fail with strict aliasing errors
474 (*(struct sockaddr_un *) &addr).sun_family = AF_UNIX;
475 addr_len = sizeof (struct sockaddr_un);
476 #if defined ZMQ_HAVE_WINDOWS
477 char buffer[MAX_PATH] = "";
478
479 TEST_ASSERT_SUCCESS_RAW_ERRNO (tmpnam_s (buffer));
480 TEST_ASSERT_SUCCESS_RAW_ERRNO (_mkdir (buffer));
481 strcat (buffer, "/ipc");
482 #else
483 char buffer[PATH_MAX] = "";
484 strcpy (buffer, "tmpXXXXXX");
485 #ifdef HAVE_MKDTEMP
486 TEST_ASSERT_TRUE (mkdtemp (buffer));
487 strcat (buffer, "/socket");
488 #else
489 int fd = mkstemp (buffer);
490 TEST_ASSERT_TRUE (fd != -1);
491 close (fd);
492 #endif
493 #endif
494 strcpy ((*(struct sockaddr_un *) &addr).sun_path, buffer);
495 memcpy (my_endpoint_, "ipc://", 7);
496 strcat (my_endpoint_, buffer);
497
498 // TODO check return value of unlink
499 unlink (buffer);
500 #else
501 return retired_fd;
502 #endif
503 }
504
505 TEST_ASSERT_SUCCESS_RAW_ERRNO (
506 bind (s_pre, (struct sockaddr *) &addr, addr_len));
507 TEST_ASSERT_SUCCESS_RAW_ERRNO (listen (s_pre, SOMAXCONN));
508
509 if (af_ == AF_INET || af_ == AF_INET6) {
510 addr_len = sizeof (struct sockaddr_storage);
511 TEST_ASSERT_SUCCESS_RAW_ERRNO (
512 getsockname (s_pre, (struct sockaddr *) &addr, &addr_len));
513 sprintf (my_endpoint_, "%s://%s:%u",
514 protocol_ == IPPROTO_TCP
515 ? "tcp"
516 : protocol_ == IPPROTO_UDP
517 ? "udp"
518 : protocol_ == IPPROTO_WSS ? "wss" : "ws",
519 address_,
520 af_ == AF_INET
521 ? ntohs ((*(struct sockaddr_in *) &addr).sin_port)
522 : ntohs ((*(struct sockaddr_in6 *) &addr).sin6_port));
523 }
524
525 return s_pre;
526 }
527
streq(const char * lhs_,const char * rhs_)528 bool streq (const char *lhs_, const char *rhs_)
529 {
530 return strcmp (lhs_, rhs_) == 0;
531 }
532
strneq(const char * lhs_,const char * rhs_)533 bool strneq (const char *lhs_, const char *rhs_)
534 {
535 return strcmp (lhs_, rhs_) != 0;
536 }
537
538 #if defined _WIN32
fuzzer_corpus_encode(const char * dirname,uint8_t *** data,size_t ** len,size_t * num_cases)539 int fuzzer_corpus_encode (const char *dirname,
540 uint8_t ***data,
541 size_t **len,
542 size_t *num_cases)
543 {
544 (void) dirname;
545 (void) data;
546 (void) len;
547 (void) num_cases;
548
549 return -1;
550 }
551
552 #else
553
fuzzer_corpus_encode(const char * dirname,uint8_t *** data,size_t ** len,size_t * num_cases)554 int fuzzer_corpus_encode (const char *dirname,
555 uint8_t ***data,
556 size_t **len,
557 size_t *num_cases)
558 {
559 TEST_ASSERT_NOT_NULL (dirname);
560 TEST_ASSERT_NOT_NULL (data);
561 TEST_ASSERT_NOT_NULL (len);
562
563 struct dirent *ent;
564 DIR *dir = opendir (dirname);
565 if (!dir)
566 return -1;
567
568 *len = NULL;
569 *data = NULL;
570 *num_cases = 0;
571
572 while ((ent = readdir (dir)) != NULL) {
573 if (!strcmp (ent->d_name, ".") || !strcmp (ent->d_name, ".."))
574 continue;
575
576 char *filename =
577 (char *) malloc (strlen (dirname) + strlen (ent->d_name) + 2);
578 TEST_ASSERT_NOT_NULL (filename);
579 strcpy (filename, dirname);
580 strcat (filename, "/");
581 strcat (filename, ent->d_name);
582 FILE *f = fopen (filename, "r");
583 free (filename);
584 if (!f)
585 continue;
586
587 fseek (f, 0, SEEK_END);
588 size_t file_len = ftell (f);
589 fseek (f, 0, SEEK_SET);
590 if (file_len == 0) {
591 fclose (f);
592 continue;
593 }
594
595 *len = (size_t *) realloc (*len, (*num_cases + 1) * sizeof (size_t));
596 TEST_ASSERT_NOT_NULL (*len);
597 *(*len + *num_cases) = file_len;
598 *data =
599 (uint8_t **) realloc (*data, (*num_cases + 1) * sizeof (uint8_t *));
600 TEST_ASSERT_NOT_NULL (*data);
601 *(*data + *num_cases) =
602 (uint8_t *) malloc (file_len * sizeof (uint8_t));
603 TEST_ASSERT_NOT_NULL (*(*data + *num_cases));
604 size_t read_bytes = 0;
605 read_bytes = fread (*(*data + *num_cases), 1, file_len, f);
606 TEST_ASSERT_EQUAL (file_len, read_bytes);
607 (*num_cases)++;
608
609 fclose (f);
610 }
611
612 closedir (dir);
613
614 return 0;
615 }
616 #endif
617