mirror of
https://github.com/zeromq/libzmq.git
synced 2025-01-14 01:37:56 +08:00
commit
12a2f81717
111
Makefile.am
111
Makefile.am
@ -1106,6 +1106,117 @@ tests_test_disconnect_msg_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_disconnect_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
endif
|
||||
|
||||
if FUZZING_ENGINE_LIB
|
||||
fuzzer_apps = tests/test_bind_null_fuzzer \
|
||||
tests/test_connect_null_fuzzer \
|
||||
tests/test_bind_fuzzer \
|
||||
tests/test_connect_fuzzer
|
||||
|
||||
tests_test_bind_null_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_bind_null_fuzzer_SOURCES = tests/test_bind_null_fuzzer.cpp
|
||||
tests_test_bind_null_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_bind_null_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_bind_null_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
tests_test_connect_null_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_connect_null_fuzzer_SOURCES = tests/test_connect_null_fuzzer.cpp
|
||||
tests_test_connect_null_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_connect_null_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_connect_null_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
tests_test_bind_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_bind_fuzzer_SOURCES = tests/test_bind_fuzzer.cpp
|
||||
tests_test_bind_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_bind_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_bind_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
tests_test_connect_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_connect_fuzzer_SOURCES = tests/test_connect_fuzzer.cpp
|
||||
tests_test_connect_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_connect_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_connect_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
if HAVE_CURVE
|
||||
fuzzer_apps += tests/test_bind_curve_fuzzer \
|
||||
tests/test_connect_curve_fuzzer \
|
||||
tests/test_z85_decode_fuzzer
|
||||
|
||||
tests_test_bind_curve_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_bind_curve_fuzzer_SOURCES = tests/test_bind_curve_fuzzer.cpp
|
||||
tests_test_bind_curve_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_bind_curve_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_bind_curve_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
tests_test_connect_curve_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_connect_curve_fuzzer_SOURCES = tests/test_connect_curve_fuzzer.cpp
|
||||
tests_test_connect_curve_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_connect_curve_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_connect_curve_fuzzer_CXXFLAGS = -std=c++11
|
||||
|
||||
tests_test_z85_decode_fuzzer_DEPENDENCIES = src/libzmq.la
|
||||
tests_test_z85_decode_fuzzer_SOURCES = tests/test_z85_decode_fuzzer.cpp
|
||||
tests_test_z85_decode_fuzzer_LDADD = ${TESTUTIL_LIBS} ${FUZZING_ENGINE_LIB} \
|
||||
$(top_builddir)/src/.libs/libzmq.a \
|
||||
${src_libzmq_la_LIBADD}
|
||||
tests_test_z85_decode_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
tests_test_z85_decode_fuzzer_CXXFLAGS = -std=c++11
|
||||
endif
|
||||
|
||||
FUZZINGdir = ${prefix}/${FUZZING_INSTALLDIR}
|
||||
FUZZING_PROGRAMS = ${fuzzer_apps}
|
||||
else
|
||||
test_apps += tests/test_bind_null_fuzzer \
|
||||
tests/test_connect_null_fuzzer \
|
||||
tests/test_bind_fuzzer \
|
||||
tests/test_connect_fuzzer
|
||||
|
||||
tests_test_bind_null_fuzzer_SOURCES = tests/test_bind_null_fuzzer.cpp
|
||||
tests_test_bind_null_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_bind_null_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
tests_test_connect_null_fuzzer_SOURCES = tests/test_connect_null_fuzzer.cpp
|
||||
tests_test_connect_null_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_connect_null_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
tests_test_bind_fuzzer_SOURCES = tests/test_bind_fuzzer.cpp
|
||||
tests_test_bind_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_bind_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
tests_test_connect_fuzzer_SOURCES = tests/test_connect_fuzzer.cpp
|
||||
tests_test_connect_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_connect_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
if HAVE_CURVE
|
||||
test_apps += tests/test_bind_curve_fuzzer \
|
||||
tests/test_connect_curve_fuzzer \
|
||||
tests/test_z85_decode_fuzzer
|
||||
|
||||
tests_test_bind_curve_fuzzer_SOURCES = tests/test_bind_curve_fuzzer.cpp
|
||||
tests_test_bind_curve_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_bind_curve_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
tests_test_connect_curve_fuzzer_SOURCES = tests/test_connect_curve_fuzzer.cpp
|
||||
tests_test_connect_curve_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_connect_curve_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
|
||||
tests_test_z85_decode_fuzzer_SOURCES = tests/test_z85_decode_fuzzer.cpp
|
||||
tests_test_z85_decode_fuzzer_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
|
||||
tests_test_z85_decode_fuzzer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
|
||||
endif
|
||||
endif
|
||||
|
||||
if ENABLE_STATIC
|
||||
# unit tests - these include individual source files and test the internal functions
|
||||
test_apps += \
|
||||
|
19
configure.ac
19
configure.ac
@ -1005,6 +1005,25 @@ AM_CONDITIONAL([WITH_CLANG_FORMAT], [$WITH_CLANG_FORMAT])
|
||||
# unittests will not build without the static libzmq.a
|
||||
AM_CONDITIONAL(ENABLE_STATIC, test "x$enable_static" = "xyes")
|
||||
|
||||
# build using a fuzzing engine - fuzzers will be built separately and statically
|
||||
AC_ARG_WITH([fuzzing-engine], [AS_HELP_STRING([--with-fuzzing-engine],
|
||||
[build libzmq with an exernal fuzzing engine [default=no]])],
|
||||
[have_fuzzing_engine_ext=$withval],
|
||||
[have_fuzzing_engine_ext=no])
|
||||
AC_ARG_WITH([fuzzing-installdir],
|
||||
AS_HELP_STRING([--with-fuzzing-installdir=PATH],
|
||||
[Path where to install fuzzer binaries]),
|
||||
[fuzzing_installdir="$withval"])
|
||||
|
||||
if test "x$have_fuzzing_engine_ext" != "xno" && test "x$fuzzing_installdir" != "x" && test "x$enable_static" = "xyes"; then
|
||||
FUZZING_ENGINE_LIB="${have_fuzzing_engine_ext}"
|
||||
FUZZING_INSTALLDIR="${fuzzing_installdir}"
|
||||
AC_SUBST(FUZZING_ENGINE_LIB)
|
||||
AC_SUBST(FUZZING_INSTALLDIR)
|
||||
AC_DEFINE(ZMQ_USE_FUZZING_ENGINE, 1, [fuzz tests will be built with fuzzing engine])
|
||||
fi
|
||||
AM_CONDITIONAL(FUZZING_ENGINE_LIB, test "x$FUZZING_ENGINE_LIB" != "x")
|
||||
|
||||
# clang 6 has a warning that does not make sense on multi-platform code
|
||||
AC_LANG_PUSH([C])
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-tautological-constant-compare],
|
||||
|
@ -75,11 +75,14 @@ set(tests
|
||||
test_mock_pub_sub)
|
||||
|
||||
if(NOT WIN32)
|
||||
list(APPEND tests test_security_gssapi test_socks)
|
||||
list(APPEND tests test_security_gssapi test_socks test_connect_null_fuzzer test_bind_null_fuzzer test_connect_fuzzer test_bind_fuzzer)
|
||||
endif()
|
||||
|
||||
if(ZMQ_HAVE_CURVE)
|
||||
list(APPEND tests test_security_curve)
|
||||
if(NOT WIN32)
|
||||
list(APPEND tests test_connect_curve_fuzzer test_bind_curve_fuzzer test_z85_decode_fuzzer)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(ENABLE_CAPSH "Run tests that require sudo and capsh (for cap_net_admin)" OFF)
|
||||
|
82
tests/test_bind_curve_fuzzer.cpp
Normal file
82
tests/test_bind_curve_fuzzer.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_security.hpp"
|
||||
|
||||
// Test that the ZMTP engine handles invalid handshake when binding
|
||||
// https://rfc.zeromq.org/spec/37/
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
void *handler;
|
||||
void *zap_thread;
|
||||
void *server;
|
||||
void *server_mon;
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
|
||||
setup_test_context ();
|
||||
setup_testutil_security_curve ();
|
||||
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
|
||||
my_endpoint);
|
||||
fd_t client = connect_socket (my_endpoint);
|
||||
|
||||
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
|
||||
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
|
||||
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
|
||||
msleep (250);
|
||||
|
||||
close (client);
|
||||
|
||||
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_bind_curve_fuzzer ()
|
||||
{
|
||||
TEST_ASSERT_SUCCESS_ERRNO (LLVMFuzzerTestOneInput (
|
||||
zmtp_greeting_curve, sizeof (zmtp_greeting_curve)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_bind_curve_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
71
tests/test_bind_fuzzer.cpp
Normal file
71
tests/test_bind_fuzzer.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
// Test that zmq_bind can handle malformed strings
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
setup_test_context ();
|
||||
std::string my_endpoint (reinterpret_cast<const char *> (data), size);
|
||||
void *socket = test_context_socket (ZMQ_PUB);
|
||||
zmq_bind (socket, my_endpoint.c_str ());
|
||||
|
||||
test_context_socket_close_zero_linger (socket);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_bind_fuzzer ()
|
||||
{
|
||||
uint8_t buffer[32] = {0};
|
||||
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
LLVMFuzzerTestOneInput (buffer, sizeof (buffer)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_bind_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
76
tests/test_bind_null_fuzzer.cpp
Normal file
76
tests/test_bind_null_fuzzer.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
// Test that the ZMTP engine handles invalid handshake when binding
|
||||
// https://rfc.zeromq.org/spec/37/
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
setup_test_context ();
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
void *server = test_context_socket (ZMQ_PUB);
|
||||
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
|
||||
fd_t client = connect_socket (my_endpoint);
|
||||
|
||||
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
|
||||
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
|
||||
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
|
||||
msleep (250);
|
||||
|
||||
close (client);
|
||||
|
||||
test_context_socket_close_zero_linger (server);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_bind_null_fuzzer ()
|
||||
{
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
LLVMFuzzerTestOneInput (zmtp_greeting_null, sizeof (zmtp_greeting_null)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_bind_null_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
85
tests/test_connect_curve_fuzzer.cpp
Normal file
85
tests/test_connect_curve_fuzzer.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_security.hpp"
|
||||
|
||||
// Test that the ZMTP engine handles invalid handshake when connecting
|
||||
// https://rfc.zeromq.org/spec/37/
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
setup_test_context ();
|
||||
setup_testutil_security_curve ();
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
|
||||
|
||||
curve_client_data_t curve_client_data = {
|
||||
valid_server_public, valid_client_public, valid_client_secret};
|
||||
void *client_mon;
|
||||
void *client = create_and_connect_client (
|
||||
my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
|
||||
|
||||
fd_t server_accept =
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
|
||||
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
|
||||
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
|
||||
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
|
||||
msleep (250);
|
||||
|
||||
close (server_accept);
|
||||
close (server);
|
||||
|
||||
test_context_socket_close_zero_linger (client);
|
||||
test_context_socket_close_zero_linger (client_mon);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_connect_curve_fuzzer ()
|
||||
{
|
||||
TEST_ASSERT_SUCCESS_ERRNO (LLVMFuzzerTestOneInput (
|
||||
zmtp_greeting_curve, sizeof (zmtp_greeting_curve)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_connect_curve_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
71
tests/test_connect_fuzzer.cpp
Normal file
71
tests/test_connect_fuzzer.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
// Test that zmq_connect can handle malformed strings
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
setup_test_context ();
|
||||
std::string my_endpoint (reinterpret_cast<const char *> (data), size);
|
||||
void *socket = test_context_socket (ZMQ_PUB);
|
||||
zmq_connect (socket, my_endpoint.c_str ());
|
||||
|
||||
test_context_socket_close_zero_linger (socket);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_connect_fuzzer ()
|
||||
{
|
||||
uint8_t buffer[32] = {0};
|
||||
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
LLVMFuzzerTestOneInput (buffer, sizeof (buffer)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_connect_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
80
tests/test_connect_null_fuzzer.cpp
Normal file
80
tests/test_connect_null_fuzzer.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
// Test that the ZMTP engine handles invalid handshake when connecting
|
||||
// https://rfc.zeromq.org/spec/37/
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
setup_test_context ();
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
|
||||
|
||||
void *client = test_context_socket (ZMQ_PUB);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
|
||||
|
||||
fd_t server_accept =
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
|
||||
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
|
||||
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
|
||||
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
|
||||
msleep (250);
|
||||
|
||||
close (server_accept);
|
||||
close (server);
|
||||
|
||||
test_context_socket_close_zero_linger (client);
|
||||
teardown_test_context ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_connect_null_fuzzer ()
|
||||
{
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
LLVMFuzzerTestOneInput (zmtp_greeting_null, sizeof (zmtp_greeting_null)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_connect_null_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
@ -91,29 +91,24 @@ static void recv_with_retry (raw_socket fd_, char *buffer_, int bytes_)
|
||||
|
||||
static void mock_handshake (raw_socket fd_, int mock_ping_)
|
||||
{
|
||||
const uint8_t zmtp_greeting[33] = {0xff, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x7f, 3, 0, 'N', 'U', 'L', 'L', 0};
|
||||
char buffer[128];
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
memcpy (buffer, zmtp_greeting, sizeof (zmtp_greeting));
|
||||
memcpy (buffer, zmtp_greeting_null, sizeof (zmtp_greeting_null));
|
||||
|
||||
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 64, 0));
|
||||
TEST_ASSERT_EQUAL_INT (64, rc);
|
||||
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
send (fd_, buffer, sizeof (zmtp_greeting_null), 0));
|
||||
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_greeting_null), rc);
|
||||
|
||||
recv_with_retry (fd_, buffer, 64);
|
||||
|
||||
const uint8_t zmtp_ready[43] = {
|
||||
4, 41, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e', 't',
|
||||
'-', 'T', 'y', 'p', 'e', 0, 0, 0, 6, 'D', 'E', 'A', 'L', 'E', 'R',
|
||||
8, 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', 0, 0, 0, 0};
|
||||
recv_with_retry (fd_, buffer, sizeof (zmtp_greeting_null));
|
||||
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
memcpy (buffer, zmtp_ready, 43);
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 43, 0));
|
||||
TEST_ASSERT_EQUAL_INT (43, rc);
|
||||
memcpy (buffer, zmtp_ready_dealer, sizeof (zmtp_ready_dealer));
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
send (fd_, buffer, sizeof (zmtp_ready_dealer), 0));
|
||||
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_dealer), rc);
|
||||
|
||||
// greeting
|
||||
recv_with_retry (fd_, buffer, 43);
|
||||
recv_with_retry (fd_, buffer, sizeof (zmtp_ready_dealer));
|
||||
|
||||
if (mock_ping_) {
|
||||
// test PING context - should be replicated in the PONG
|
||||
@ -226,21 +221,7 @@ static void test_heartbeat_timeout (int server_type_, int mock_ping_)
|
||||
prep_server_socket (!mock_ping_, 0, &server, &server_mon, my_endpoint,
|
||||
MAX_SOCKET_STRING, server_type_);
|
||||
|
||||
struct sockaddr_in ip4addr;
|
||||
raw_socket s;
|
||||
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (atoi (strrchr (my_endpoint, ':') + 1));
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
connect (s, (struct sockaddr *) &ip4addr, sizeof ip4addr));
|
||||
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
// Mock a ZMTP 3 client so we can forcibly time out a connection
|
||||
mock_handshake (s, mock_ping_);
|
||||
|
@ -19,17 +19,6 @@
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
#if defined(ZMQ_HAVE_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdexcept>
|
||||
#define close closesocket
|
||||
typedef SOCKET raw_socket;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
typedef int raw_socket;
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -67,7 +56,7 @@ static int get_monitor_event (void *monitor_)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void recv_with_retry (raw_socket fd_, char *buffer_, int bytes_)
|
||||
static void recv_with_retry (fd_t fd_, char *buffer_, int bytes_)
|
||||
{
|
||||
int received = 0;
|
||||
while (true) {
|
||||
@ -81,13 +70,11 @@ static void recv_with_retry (raw_socket fd_, char *buffer_, int bytes_)
|
||||
}
|
||||
}
|
||||
|
||||
static void mock_handshake (raw_socket fd_, bool sub_command, bool mock_pub)
|
||||
static void mock_handshake (fd_t fd_, bool sub_command, bool mock_pub)
|
||||
{
|
||||
const uint8_t zmtp_greeting[33] = {0xff, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x7f, 3, 0, 'N', 'U', 'L', 'L', 0};
|
||||
char buffer[128];
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
memcpy (buffer, zmtp_greeting, sizeof (zmtp_greeting));
|
||||
memcpy (buffer, zmtp_greeting_null, sizeof (zmtp_greeting_null));
|
||||
|
||||
// Mock ZMTP 3.1 which uses commands
|
||||
if (sub_command) {
|
||||
@ -99,24 +86,20 @@ static void mock_handshake (raw_socket fd_, bool sub_command, bool mock_pub)
|
||||
recv_with_retry (fd_, buffer, 64);
|
||||
|
||||
if (!mock_pub) {
|
||||
const uint8_t zmtp_ready[27] = {
|
||||
4, 25, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e',
|
||||
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 3, 'S', 'U', 'B'};
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
send (fd_, (const char *) zmtp_ready, 27, 0));
|
||||
TEST_ASSERT_EQUAL_INT (27, rc);
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
|
||||
fd_, (const char *) zmtp_ready_sub, sizeof (zmtp_ready_sub), 0));
|
||||
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_sub), rc);
|
||||
} else {
|
||||
const uint8_t zmtp_ready[28] = {
|
||||
4, 26, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e',
|
||||
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 4, 'X', 'P', 'U', 'B'};
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
send (fd_, (const char *) zmtp_ready, 28, 0));
|
||||
TEST_ASSERT_EQUAL_INT (28, rc);
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
|
||||
fd_, (const char *) zmtp_ready_xpub, sizeof (zmtp_ready_xpub), 0));
|
||||
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_xpub), rc);
|
||||
}
|
||||
|
||||
// greeting - XPUB has one extra byte
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
recv_with_retry (fd_, buffer, mock_pub ? 27 : 28);
|
||||
recv_with_retry (fd_, buffer,
|
||||
mock_pub ? sizeof (zmtp_ready_sub)
|
||||
: sizeof (zmtp_ready_xpub));
|
||||
}
|
||||
|
||||
static void prep_server_socket (void **server_out_,
|
||||
@ -158,21 +141,7 @@ static void test_mock_pub_sub (bool sub_command_, bool mock_pub_)
|
||||
prep_server_socket (&server, &server_mon, my_endpoint, MAX_SOCKET_STRING,
|
||||
mock_pub_ ? ZMQ_SUB : ZMQ_XPUB);
|
||||
|
||||
struct sockaddr_in ip4addr;
|
||||
raw_socket s;
|
||||
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (atoi (strrchr (my_endpoint, ':') + 1));
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
connect (s, (struct sockaddr *) &ip4addr, sizeof ip4addr));
|
||||
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
// Mock a ZMTP 3 client so we can forcibly try sub commands
|
||||
mock_handshake (s, sub_command_, mock_pub_);
|
||||
|
@ -47,17 +47,6 @@
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_security.hpp"
|
||||
#if defined(ZMQ_HAVE_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdexcept>
|
||||
#define close closesocket
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <unity.h>
|
||||
|
||||
#include "../src/tweetnacl.h"
|
||||
@ -223,34 +212,10 @@ void test_curve_security_with_plain_client_credentials ()
|
||||
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
|
||||
}
|
||||
|
||||
fd_t connect_vanilla_socket (char *my_endpoint_)
|
||||
{
|
||||
fd_t s;
|
||||
struct sockaddr_in ip4addr;
|
||||
|
||||
unsigned short int port;
|
||||
int rc = sscanf (my_endpoint_, "tcp://127.0.0.1:%hu", &port);
|
||||
TEST_ASSERT_EQUAL_INT (1, rc);
|
||||
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (port);
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = connect (s, reinterpret_cast<struct sockaddr *> (&ip4addr),
|
||||
sizeof (ip4addr));
|
||||
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
||||
return s;
|
||||
}
|
||||
|
||||
void test_curve_security_unauthenticated_message ()
|
||||
{
|
||||
// Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
fd_t s = connect_vanilla_socket (my_endpoint);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
// send anonymous ZMTP/1.0 greeting
|
||||
send (s, "\x01\x00", 2, 0);
|
||||
// send sneaky message that shouldn't be received
|
||||
@ -277,21 +242,16 @@ template <size_t N> void send (fd_t fd_, const char (&data_)[N])
|
||||
send_all (fd_, data_, N - 1);
|
||||
}
|
||||
|
||||
void send_greeting (fd_t s_)
|
||||
template <size_t N> void send (fd_t fd_, const uint8_t (&data_)[N])
|
||||
{
|
||||
send (s_, "\xff\0\0\0\0\0\0\0\0\x7f"); // signature
|
||||
send (s_, "\x03\x00"); // version 3.0
|
||||
send (s_, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); // mechanism CURVE
|
||||
send (s_, "\0"); // as-server == false
|
||||
send (s_, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
||||
send_all (fd_, reinterpret_cast<const char *> (&data_), N);
|
||||
}
|
||||
|
||||
void test_curve_security_invalid_hello_wrong_length ()
|
||||
{
|
||||
fd_t s = connect_vanilla_socket (my_endpoint);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
// send GREETING
|
||||
send_greeting (s);
|
||||
send (s, zmtp_greeting_curve);
|
||||
|
||||
// send CURVE HELLO of wrong size
|
||||
send (s, "\x04\x06\x05HELLO");
|
||||
@ -355,9 +315,9 @@ template <size_t N> void send_command (fd_t s_, char (&command_)[N])
|
||||
|
||||
void test_curve_security_invalid_hello_command_name ()
|
||||
{
|
||||
fd_t s = connect_vanilla_socket (my_endpoint);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
send_greeting (s);
|
||||
send (s, zmtp_greeting_curve);
|
||||
|
||||
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
||||
|
||||
@ -377,9 +337,9 @@ void test_curve_security_invalid_hello_command_name ()
|
||||
|
||||
void test_curve_security_invalid_hello_version ()
|
||||
{
|
||||
fd_t s = connect_vanilla_socket (my_endpoint);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
send_greeting (s);
|
||||
send (s, zmtp_greeting_curve);
|
||||
|
||||
zmq::curve_client_tools_t tools = make_curve_client_tools ();
|
||||
|
||||
@ -429,9 +389,9 @@ void recv_greeting (fd_t fd_)
|
||||
fd_t connect_exchange_greeting_and_send_hello (
|
||||
char *my_endpoint_, zmq::curve_client_tools_t &tools_)
|
||||
{
|
||||
fd_t s = connect_vanilla_socket (my_endpoint_);
|
||||
fd_t s = connect_socket (my_endpoint_);
|
||||
|
||||
send_greeting (s);
|
||||
send (s, zmtp_greeting_curve);
|
||||
recv_greeting (s);
|
||||
|
||||
// send valid CURVE HELLO
|
||||
|
@ -30,17 +30,6 @@
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_monitoring.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
#if defined(ZMQ_HAVE_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdexcept>
|
||||
#define close closesocket
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -253,23 +242,7 @@ void test_plain_creds ()
|
||||
// Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
void test_vanilla_socket ()
|
||||
{
|
||||
struct sockaddr_in ip4addr;
|
||||
int s;
|
||||
unsigned short int port;
|
||||
int rc = sscanf (my_endpoint, "tcp://127.0.0.1:%hu", &port);
|
||||
TEST_ASSERT_EQUAL_INT (1, rc);
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (port);
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = connect (s, reinterpret_cast<struct sockaddr *> (&ip4addr),
|
||||
sizeof (ip4addr));
|
||||
TEST_ASSERT_GREATER_THAN (-1, rc);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
// send anonymous ZMTP/1.0 greeting
|
||||
send (s, "\x01\x00", 2, 0);
|
||||
// send sneaky message that shouldn't be received
|
||||
|
@ -169,25 +169,8 @@ void test_vanilla_socket ()
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
|
||||
|
||||
struct sockaddr_in ip4addr;
|
||||
fd_t s;
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
|
||||
unsigned short int port;
|
||||
int rc = sscanf (my_endpoint, "tcp://127.0.0.1:%hu", &port);
|
||||
TEST_ASSERT_EQUAL_INT (1, rc);
|
||||
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (port);
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = connect (s, reinterpret_cast<struct sockaddr *> (&ip4addr),
|
||||
sizeof ip4addr);
|
||||
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
||||
// send anonymous ZMTP/1.0 greeting
|
||||
send (s, "\x01\x00", 2, 0);
|
||||
// send sneaky message that shouldn't be received
|
||||
|
@ -30,18 +30,6 @@
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
#if defined(ZMQ_HAVE_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdexcept>
|
||||
#define close closesocket
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -195,25 +183,7 @@ void test_plain_wrong_credentials_fails ()
|
||||
void test_plain_vanilla_socket ()
|
||||
{
|
||||
// Unauthenticated messages from a vanilla socket shouldn't be received
|
||||
struct sockaddr_in ip4addr;
|
||||
fd_t s;
|
||||
|
||||
unsigned short int port;
|
||||
int rc = sscanf (my_endpoint, "tcp://127.0.0.1:%hu", &port);
|
||||
TEST_ASSERT_EQUAL_INT (1, rc);
|
||||
|
||||
ip4addr.sin_family = AF_INET;
|
||||
ip4addr.sin_port = htons (port);
|
||||
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
|
||||
ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
|
||||
#else
|
||||
inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
|
||||
#endif
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
rc = connect (s, reinterpret_cast<struct sockaddr *> (&ip4addr),
|
||||
sizeof (ip4addr));
|
||||
TEST_ASSERT_GREATER_THAN_INT (-1, rc);
|
||||
fd_t s = connect_socket (my_endpoint);
|
||||
// send anonymous ZMTP/1.0 greeting
|
||||
send (s, "\x01\x00", 2, 0);
|
||||
// send sneaky message that shouldn't be received
|
||||
|
@ -43,12 +43,13 @@ void tearDown ()
|
||||
#define THREAD_COUNT 100
|
||||
|
||||
extern "C" {
|
||||
static void *worker (void *s_)
|
||||
static void *worker (void *ctx)
|
||||
{
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (s_, "tipc://{5560,0}@0.0.0"));
|
||||
void *s = zmq_socket (ctx, ZMQ_SUB);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (s, "tipc://{5560,0}@0.0.0"));
|
||||
|
||||
// Start closing the socket while the connecting process is underway.
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (s_));
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (s));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -57,7 +58,6 @@ static void *worker (void *s_)
|
||||
void test_shutdown_stress_tipc ()
|
||||
{
|
||||
void *s1;
|
||||
void *s2;
|
||||
int i;
|
||||
int j;
|
||||
pthread_t threads[THREAD_COUNT];
|
||||
@ -72,9 +72,8 @@ void test_shutdown_stress_tipc ()
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s1, "tipc://{5560,0,0}"));
|
||||
|
||||
for (i = 0; i != THREAD_COUNT; i++) {
|
||||
s2 = zmq_socket (get_test_context (), ZMQ_SUB);
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
pthread_create (&threads[i], NULL, worker, s2));
|
||||
pthread_create (&threads[i], NULL, worker, get_test_context ()));
|
||||
}
|
||||
|
||||
for (i = 0; i != THREAD_COUNT; i++) {
|
||||
|
@ -105,21 +105,10 @@ void *setup_socks_server (char *socks_server_address,
|
||||
int socks_server_address_len)
|
||||
{
|
||||
fprintf (stderr, "socks_server: setup socks server\n");
|
||||
int server_fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
TEST_ASSERT_NOT_EQUAL (-1, server_fd);
|
||||
int flag = 1;
|
||||
int res;
|
||||
#ifdef _WIN32
|
||||
res = setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag,
|
||||
sizeof (int));
|
||||
#else
|
||||
res = setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int));
|
||||
#endif
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (res);
|
||||
struct sockaddr_in saddr = bind_bsd_socket (server_fd);
|
||||
int nbytes = snprintf (socks_server_address, socks_server_address_len,
|
||||
"127.0.0.1:%d", ntohs (saddr.sin_port));
|
||||
TEST_ASSERT (nbytes >= 0 && nbytes < socks_server_address_len);
|
||||
int server_fd =
|
||||
bind_socket_resolve_port ("127.0.0.1", "0", socks_server_address);
|
||||
memmove (socks_server_address, strchr (socks_server_address, '/') + 2,
|
||||
strlen (strchr (socks_server_address, '/') + 1));
|
||||
fprintf (stderr, "socks_server: bound to: tcp://%s\n",
|
||||
socks_server_address);
|
||||
return (void *) (intptr_t) server_fd;
|
||||
|
@ -32,12 +32,6 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
SETUP_TEARDOWN_TESTCONTEXT
|
||||
|
||||
void test_stream_exceeds_buffer ()
|
||||
@ -47,16 +41,7 @@ void test_stream_exceeds_buffer ()
|
||||
unsigned char rcvbuf[msgsize];
|
||||
char my_endpoint[MAX_SOCKET_STRING];
|
||||
|
||||
int server_sock =
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (socket (AF_INET, SOCK_STREAM, 0));
|
||||
int enable = 1;
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (setsockopt (server_sock, SOL_SOCKET,
|
||||
SO_REUSEADDR, (char *) &enable,
|
||||
sizeof (enable)));
|
||||
struct sockaddr_in saddr = bind_bsd_socket (server_sock);
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (listen (server_sock, 1));
|
||||
|
||||
sprintf (my_endpoint, "tcp://127.0.0.1:%d", ntohs (saddr.sin_port));
|
||||
int server_sock = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
|
||||
|
||||
void *zsock = test_context_socket (ZMQ_STREAM);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (zsock, my_endpoint));
|
||||
|
@ -37,33 +37,12 @@
|
||||
SETUP_TEARDOWN_TESTCONTEXT
|
||||
|
||||
#if !defined(ZMQ_HAVE_WINDOWS)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int setup_socket_and_set_fd (void *zmq_socket_,
|
||||
int af_,
|
||||
int protocol_,
|
||||
const sockaddr *addr_,
|
||||
size_t addr_len_)
|
||||
void pre_allocate_sock_tcp (void *socket_, char *my_endpoint_)
|
||||
{
|
||||
const int s_pre =
|
||||
TEST_ASSERT_SUCCESS_ERRNO (socket (af_, SOCK_STREAM, protocol_));
|
||||
|
||||
if (af_ == AF_INET) {
|
||||
int flag = 1;
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
setsockopt (s_pre, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)));
|
||||
}
|
||||
|
||||
TEST_ASSERT_SUCCESS_ERRNO (bind (s_pre, addr_, addr_len_));
|
||||
TEST_ASSERT_SUCCESS_ERRNO (listen (s_pre, SOMAXCONN));
|
||||
|
||||
fd_t s = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint_);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
zmq_setsockopt (zmq_socket_, ZMQ_USE_FD, &s_pre, sizeof (s_pre)));
|
||||
|
||||
return s_pre;
|
||||
zmq_setsockopt (socket_, ZMQ_USE_FD, &s, sizeof (s)));
|
||||
}
|
||||
|
||||
typedef void (*pre_allocate_sock_fun_t) (void *, char *);
|
||||
@ -166,41 +145,6 @@ void test_client_server (pre_allocate_sock_fun_t pre_allocate_sock_fun_)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t pre_allocate_sock_tcp_int (void *zmq_socket_,
|
||||
const char *address_,
|
||||
const char *port_)
|
||||
{
|
||||
struct addrinfo *addr, hint;
|
||||
hint.ai_flags = 0;
|
||||
hint.ai_family = AF_INET;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_addrlen = 0;
|
||||
hint.ai_canonname = NULL;
|
||||
hint.ai_addr = NULL;
|
||||
hint.ai_next = NULL;
|
||||
|
||||
TEST_ASSERT_SUCCESS_ERRNO (getaddrinfo (address_, port_, &hint, &addr));
|
||||
|
||||
const int s_pre = setup_socket_and_set_fd (
|
||||
zmq_socket_, AF_INET, IPPROTO_TCP, addr->ai_addr, addr->ai_addrlen);
|
||||
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof (sin);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
getsockname (s_pre, (struct sockaddr *) &sin, &len));
|
||||
|
||||
freeaddrinfo (addr);
|
||||
|
||||
return ntohs (sin.sin_port);
|
||||
}
|
||||
|
||||
void pre_allocate_sock_tcp (void *socket_, char *my_endpoint_)
|
||||
{
|
||||
const uint16_t port = pre_allocate_sock_tcp_int (socket_, "127.0.0.1", "0");
|
||||
sprintf (my_endpoint_, "tcp://127.0.0.1:%u", port);
|
||||
}
|
||||
|
||||
void test_req_rep_tcp ()
|
||||
{
|
||||
test_req_rep (pre_allocate_sock_tcp);
|
||||
@ -218,38 +162,14 @@ void test_client_server_tcp ()
|
||||
#endif
|
||||
}
|
||||
|
||||
void pre_allocate_sock_ipc_int (void *zmq_socket_, const char *path_)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy (addr.sun_path, path_);
|
||||
|
||||
// TODO check return value of unlink
|
||||
unlink (path_);
|
||||
|
||||
setup_socket_and_set_fd (zmq_socket_, AF_UNIX, 0,
|
||||
reinterpret_cast<struct sockaddr *> (&addr),
|
||||
sizeof (struct sockaddr_un));
|
||||
}
|
||||
|
||||
char ipc_endpoint[16];
|
||||
char ipc_endpoint[MAX_SOCKET_STRING] = "";
|
||||
|
||||
void pre_allocate_sock_ipc (void *sb_, char *my_endpoint_)
|
||||
{
|
||||
strcpy (ipc_endpoint, "tmpXXXXXX");
|
||||
|
||||
#ifdef HAVE_MKDTEMP
|
||||
TEST_ASSERT_TRUE (mkdtemp (ipc_endpoint));
|
||||
strcat (ipc_endpoint, "/ipc");
|
||||
#else
|
||||
int fd = mkstemp (ipc_endpoint);
|
||||
TEST_ASSERT_TRUE (fd != -1);
|
||||
close (fd);
|
||||
#endif
|
||||
|
||||
pre_allocate_sock_ipc_int (sb_, ipc_endpoint);
|
||||
strcpy (my_endpoint_, "ipc://");
|
||||
strcat (my_endpoint_, ipc_endpoint);
|
||||
fd_t s = bind_socket_resolve_port ("", "", my_endpoint_, AF_UNIX, 0);
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
zmq_setsockopt (sb_, ZMQ_USE_FD, &s, sizeof (s)));
|
||||
strcpy (ipc_endpoint, strchr (my_endpoint_, '/') + 2);
|
||||
}
|
||||
|
||||
void test_req_rep_ipc ()
|
||||
@ -277,7 +197,7 @@ void test_client_server_ipc ()
|
||||
|
||||
int main ()
|
||||
{
|
||||
setup_test_environment ();
|
||||
setup_test_environment (0);
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_req_rep_tcp);
|
||||
|
75
tests/test_z85_decode_fuzzer.cpp
Normal file
75
tests/test_z85_decode_fuzzer.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ZMQ_USE_FUZZING_ENGINE
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "testutil.hpp"
|
||||
#include "testutil_unity.hpp"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
uint8_t *secret_key;
|
||||
|
||||
// As per API definition, input must be divisible by 5, so truncate it if it's not
|
||||
size -= size % 5;
|
||||
// As per API definition, the destination must be at least 0.8 times the input data
|
||||
TEST_ASSERT_NOT_NULL (secret_key = (uint8_t *) malloc (size * 4 / 5));
|
||||
|
||||
std::string z85_secret_key (reinterpret_cast<const char *> (data), size);
|
||||
TEST_ASSERT_NOT_NULL (zmq_z85_decode (secret_key, z85_secret_key.c_str ()));
|
||||
|
||||
free (secret_key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ZMQ_USE_FUZZING_ENGINE
|
||||
void test_bind_null_fuzzer ()
|
||||
{
|
||||
uint8_t buffer[32] = {0};
|
||||
|
||||
TEST_ASSERT_SUCCESS_ERRNO (
|
||||
LLVMFuzzerTestOneInput (buffer, sizeof (buffer)));
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setup_test_environment ();
|
||||
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_bind_null_fuzzer);
|
||||
|
||||
return UNITY_END ();
|
||||
}
|
||||
#endif
|
@ -35,6 +35,10 @@
|
||||
#if defined _WIN32
|
||||
#include "../src/windows.hpp"
|
||||
#if defined _MSC_VER
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
#include <direct.h>
|
||||
#include <afunix.h>
|
||||
#endif
|
||||
#include <crtdbg.h>
|
||||
#pragma warning(disable : 4996)
|
||||
// iphlpapi is needed for if_nametoindex (not on Windows XP)
|
||||
@ -55,6 +59,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
#if defined(ZMQ_HAVE_AIX)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socketvar.h>
|
||||
@ -365,6 +370,147 @@ sockaddr_in bind_bsd_socket (int socket_)
|
||||
return saddr;
|
||||
}
|
||||
|
||||
fd_t connect_socket (const char *endpoint_, const int af_, const int protocol_)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
// OSX is very opinionated and wants the size to match the AF family type
|
||||
socklen_t addr_len = sizeof (addr);
|
||||
const fd_t s_pre = socket (af_, SOCK_STREAM, protocol_);
|
||||
TEST_ASSERT_NOT_EQUAL (-1, s_pre);
|
||||
|
||||
if (af_ == AF_INET || af_ == AF_INET6) {
|
||||
const char *port = strrchr (endpoint_, ':') + 1;
|
||||
char address[MAX_SOCKET_STRING];
|
||||
// getaddrinfo does not like [x:y::z]
|
||||
if (*strchr (endpoint_, '/') + 2 == '[') {
|
||||
strcpy (address, strchr (endpoint_, '[') + 1);
|
||||
address[strlen (address) - strlen (port) - 2] = '\0';
|
||||
} else {
|
||||
strcpy (address, strchr (endpoint_, '/') + 2);
|
||||
address[strlen (address) - strlen (port) - 1] = '\0';
|
||||
}
|
||||
|
||||
struct addrinfo *in, hint;
|
||||
hint.ai_flags = AI_NUMERICSERV;
|
||||
hint.ai_family = af_;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = protocol_;
|
||||
hint.ai_addrlen = 0;
|
||||
hint.ai_canonname = NULL;
|
||||
hint.ai_addr = NULL;
|
||||
hint.ai_next = NULL;
|
||||
|
||||
TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (
|
||||
getaddrinfo (address, port, &hint, &in));
|
||||
TEST_ASSERT_NOT_NULL (in);
|
||||
memcpy (&addr, in->ai_addr, in->ai_addrlen);
|
||||
addr_len = (socklen_t) in->ai_addrlen;
|
||||
freeaddrinfo (in);
|
||||
}
|
||||
#if defined(ZMQ_HAVE_IPC)
|
||||
else {
|
||||
struct sockaddr_un *un_addr = (struct sockaddr_un *) &addr;
|
||||
addr_len = sizeof (struct sockaddr_un);
|
||||
un_addr->sun_family = AF_UNIX;
|
||||
strcpy (un_addr->sun_path, endpoint_);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
connect (s_pre, (struct sockaddr *) &addr, addr_len));
|
||||
|
||||
return s_pre;
|
||||
}
|
||||
|
||||
fd_t bind_socket_resolve_port (const char *address_,
|
||||
const char *port_,
|
||||
char *my_endpoint_,
|
||||
const int af_,
|
||||
const int protocol_)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
// OSX is very opinionated and wants the size to match the AF family type
|
||||
socklen_t addr_len = sizeof (addr);
|
||||
const fd_t s_pre = socket (af_, SOCK_STREAM, protocol_);
|
||||
TEST_ASSERT_NOT_EQUAL (-1, s_pre);
|
||||
|
||||
if (af_ == AF_INET || af_ == AF_INET6) {
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
const char flag = '\1';
|
||||
#elif defined ZMQ_HAVE_VXWORKS
|
||||
char flag = '\1';
|
||||
#else
|
||||
int flag = 1;
|
||||
#endif
|
||||
struct addrinfo *in, hint;
|
||||
hint.ai_flags = AI_NUMERICSERV;
|
||||
hint.ai_family = af_;
|
||||
hint.ai_socktype = protocol_ == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hint.ai_protocol = protocol_;
|
||||
hint.ai_addrlen = 0;
|
||||
hint.ai_canonname = NULL;
|
||||
hint.ai_addr = NULL;
|
||||
hint.ai_next = NULL;
|
||||
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
setsockopt (s_pre, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)));
|
||||
TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (
|
||||
getaddrinfo (address_, port_, &hint, &in));
|
||||
TEST_ASSERT_NOT_NULL (in);
|
||||
memcpy (&addr, in->ai_addr, in->ai_addrlen);
|
||||
addr_len = (socklen_t) in->ai_addrlen;
|
||||
freeaddrinfo (in);
|
||||
}
|
||||
#if defined(ZMQ_HAVE_IPC)
|
||||
else {
|
||||
struct sockaddr_un *un_addr = (struct sockaddr_un *) &addr;
|
||||
addr_len = sizeof (struct sockaddr_un);
|
||||
un_addr->sun_family = AF_UNIX;
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
char buffer[MAX_PATH] = "";
|
||||
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (tmpnam_s (buffer));
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (_mkdir (buffer));
|
||||
strcat (buffer, "/ipc");
|
||||
#else
|
||||
char buffer[PATH_MAX] = "";
|
||||
strcpy (buffer, "tmpXXXXXX");
|
||||
#ifdef HAVE_MKDTEMP
|
||||
TEST_ASSERT_TRUE (mkdtemp (buffer));
|
||||
strcat (buffer, "/socket");
|
||||
#else
|
||||
int fd = mkstemp (buffer);
|
||||
TEST_ASSERT_TRUE (fd != -1);
|
||||
close (fd);
|
||||
#endif
|
||||
#endif
|
||||
strcpy (un_addr->sun_path, buffer);
|
||||
memcpy (my_endpoint_, "ipc://", 7);
|
||||
strcat (my_endpoint_, buffer);
|
||||
|
||||
// TODO check return value of unlink
|
||||
unlink (buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
bind (s_pre, (struct sockaddr *) &addr, addr_len));
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (listen (s_pre, SOMAXCONN));
|
||||
|
||||
if (af_ == AF_INET || af_ == AF_INET6) {
|
||||
addr_len = sizeof (struct sockaddr_storage);
|
||||
TEST_ASSERT_SUCCESS_RAW_ERRNO (
|
||||
getsockname (s_pre, (struct sockaddr *) &addr, &addr_len));
|
||||
sprintf (my_endpoint_, "%s://%s:%u",
|
||||
protocol_ == IPPROTO_TCP ? "tcp" : "udp", address_,
|
||||
af_ == AF_INET
|
||||
? ntohs (((struct sockaddr_in *) &addr)->sin_port)
|
||||
: ntohs (((struct sockaddr_in6 *) &addr)->sin6_port));
|
||||
}
|
||||
|
||||
return s_pre;
|
||||
}
|
||||
|
||||
bool streq (const char *lhs_, const char *rhs_)
|
||||
{
|
||||
return strcmp (lhs_, rhs_) == 0;
|
||||
|
@ -38,6 +38,14 @@
|
||||
#include "../include/zmq.h"
|
||||
#include "../src/stdint.hpp"
|
||||
|
||||
// For AF_INET and IPPROTO_TCP
|
||||
#if defined _WIN32
|
||||
#include "../src/windows.hpp"
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// This defines the settle time used in tests; raise this if we
|
||||
// get test failures on slower systems due to binds/connects not
|
||||
// settled. Tested to work reliably at 1 msec on a fast PC.
|
||||
@ -57,8 +65,33 @@
|
||||
#define ENDPOINT_5 "udp://127.0.0.1:5560"
|
||||
#define PORT_6 5561
|
||||
|
||||
// For tests that mock ZMTP
|
||||
const uint8_t zmtp_greeting_null[64] = {
|
||||
0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0x7f, 3, 0, 'N', 'U', 'L', 'L',
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
const uint8_t zmtp_greeting_curve[64] = {
|
||||
0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0x7f, 3, 0, 'C', 'U', 'R', 'V',
|
||||
'E', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const uint8_t zmtp_ready_dealer[43] = {
|
||||
4, 41, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e', 't',
|
||||
'-', 'T', 'y', 'p', 'e', 0, 0, 0, 6, 'D', 'E', 'A', 'L', 'E', 'R',
|
||||
8, 'I', 'd', 'e', 'n', 't', 'i', 't', 'y', 0, 0, 0, 0};
|
||||
const uint8_t zmtp_ready_xpub[28] = {
|
||||
4, 26, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e',
|
||||
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 4, 'X', 'P', 'U', 'B'};
|
||||
const uint8_t zmtp_ready_sub[27] = {
|
||||
4, 25, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e',
|
||||
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 3, 'S', 'U', 'B'};
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
// duplicated from fd.hpp
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
@ -172,4 +205,20 @@ int test_inet_pton (int af_, const char *src_, void *dst_);
|
||||
// Binds an ipv4 BSD socket to an ephemeral port, returns the compiled sockaddr
|
||||
struct sockaddr_in bind_bsd_socket (int socket);
|
||||
|
||||
// Connects a BSD socket to the ZMQ endpoint. Works with ipv4/ipv6/unix.
|
||||
fd_t connect_socket (const char *endpoint_,
|
||||
const int af_ = AF_INET,
|
||||
const int protocol_ = IPPROTO_TCP);
|
||||
|
||||
// Binds a BSD socket to an ephemeral port, returns the file descriptor.
|
||||
// The resulting ZMQ endpoint will be stored in my_endpoint, including the protocol
|
||||
// prefix, so ensure it is writable and of appropriate size.
|
||||
// Works with ipv4/ipv6/unix. With unix sockets address_/port_ can be empty and
|
||||
// my_endpoint_ will contain a random path.
|
||||
fd_t bind_socket_resolve_port (const char *address_,
|
||||
const char *port_,
|
||||
char *my_endpoint_,
|
||||
const int af_ = AF_INET,
|
||||
const int protocol_ = IPPROTO_TCP);
|
||||
|
||||
#endif
|
||||
|
@ -55,12 +55,10 @@ int test_assert_success_message_errno_helper (int rc_,
|
||||
return rc_;
|
||||
}
|
||||
|
||||
int test_assert_success_message_raw_errno_helper (int rc_,
|
||||
const char *msg_,
|
||||
const char *expr_,
|
||||
int line_)
|
||||
int test_assert_success_message_raw_errno_helper (
|
||||
int rc_, const char *msg_, const char *expr_, int line_, bool zero)
|
||||
{
|
||||
if (rc_ == -1) {
|
||||
if (rc_ == -1 || (zero && rc_ != 0)) {
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
int current_errno = WSAGetLastError ();
|
||||
#else
|
||||
@ -70,14 +68,24 @@ int test_assert_success_message_raw_errno_helper (int rc_,
|
||||
char buffer[512];
|
||||
buffer[sizeof (buffer) - 1] =
|
||||
0; // to ensure defined behavior with VC++ <= 2013
|
||||
snprintf (buffer, sizeof (buffer) - 1, "%s failed%s%s%s, errno = %i",
|
||||
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
|
||||
msg_ ? ")" : "", current_errno);
|
||||
snprintf (
|
||||
buffer, sizeof (buffer) - 1, "%s failed%s%s%s with %d, errno = %i/%s",
|
||||
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
|
||||
msg_ ? ")" : "", rc_, current_errno, strerror (current_errno));
|
||||
UNITY_TEST_FAIL (line_, buffer);
|
||||
}
|
||||
return rc_;
|
||||
}
|
||||
|
||||
int test_assert_success_message_raw_zero_errno_helper (int rc_,
|
||||
const char *msg_,
|
||||
const char *expr_,
|
||||
int line_)
|
||||
{
|
||||
return test_assert_success_message_raw_errno_helper (rc_, msg_, expr_,
|
||||
line_, true);
|
||||
}
|
||||
|
||||
int test_assert_failure_message_raw_errno_helper (
|
||||
int rc_, int expected_errno_, const char *msg_, const char *expr_, int line_)
|
||||
{
|
||||
|
@ -43,10 +43,13 @@ int test_assert_success_message_errno_helper (int rc_,
|
||||
const char *expr_,
|
||||
int line);
|
||||
|
||||
int test_assert_success_message_raw_errno_helper (int rc_,
|
||||
const char *msg_,
|
||||
const char *expr_,
|
||||
int line);
|
||||
int test_assert_success_message_raw_errno_helper (
|
||||
int rc_, const char *msg_, const char *expr_, int line, bool zero_ = false);
|
||||
|
||||
int test_assert_success_message_raw_zero_errno_helper (int rc_,
|
||||
const char *msg_,
|
||||
const char *expr_,
|
||||
int line);
|
||||
|
||||
int test_assert_failure_message_raw_errno_helper (
|
||||
int rc_, int expected_errno_, const char *msg_, const char *expr_, int line);
|
||||
@ -88,9 +91,22 @@ int test_assert_failure_message_raw_errno_helper (
|
||||
// A typical use would be:
|
||||
// TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0));
|
||||
// In case of success, the result of the macro is the result of 'expr'.
|
||||
// Success is strictly defined by a return value different from -1, as opposed
|
||||
// to checking that it is 0, like TEST_ASSERT_FAILURE_RAW_ZERO_ERRNO does.
|
||||
#define TEST_ASSERT_SUCCESS_RAW_ERRNO(expr) \
|
||||
test_assert_success_message_raw_errno_helper (expr, NULL, #expr, __LINE__)
|
||||
|
||||
// Asserts that the socket API 'expr' is successful. In case of a failure, the
|
||||
// assertion message includes the literal 'expr' and the error code.
|
||||
// A typical use would be:
|
||||
// TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (send (fd, buffer, 64, 0));
|
||||
// In case of success, the result of the macro is the result of 'expr'.
|
||||
// Success is strictly defined by a return value of 0, as opposed to checking
|
||||
// that it is not -1, like TEST_ASSERT_FAILURE_RAW_ERRNO does.
|
||||
#define TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO(expr) \
|
||||
test_assert_success_message_raw_zero_errno_helper (expr, NULL, #expr, \
|
||||
__LINE__)
|
||||
|
||||
// Asserts that the socket API 'expr' is not successful, and the error code is
|
||||
// 'error_code'. In case of an unexpected succces, or a failure with an
|
||||
// unexpected error code, the assertion message includes the literal 'expr'
|
||||
|
Loading…
x
Reference in New Issue
Block a user