Unverified Commit 12a2f817 authored by Luca Boccassi's avatar Luca Boccassi Committed by GitHub

Merge pull request #3885 from bluca/fuzzers

Problem: no fuzz testing
parents b56195e9 96787c35
...@@ -1106,6 +1106,117 @@ tests_test_disconnect_msg_LDADD = ${TESTUTIL_LIBS} src/libzmq.la ...@@ -1106,6 +1106,117 @@ tests_test_disconnect_msg_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_disconnect_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS} tests_test_disconnect_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif 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 if ENABLE_STATIC
# unit tests - these include individual source files and test the internal functions # unit tests - these include individual source files and test the internal functions
test_apps += \ test_apps += \
......
...@@ -1005,6 +1005,25 @@ AM_CONDITIONAL([WITH_CLANG_FORMAT], [$WITH_CLANG_FORMAT]) ...@@ -1005,6 +1005,25 @@ AM_CONDITIONAL([WITH_CLANG_FORMAT], [$WITH_CLANG_FORMAT])
# unittests will not build without the static libzmq.a # unittests will not build without the static libzmq.a
AM_CONDITIONAL(ENABLE_STATIC, test "x$enable_static" = "xyes") 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 # clang 6 has a warning that does not make sense on multi-platform code
AC_LANG_PUSH([C]) AC_LANG_PUSH([C])
AX_CHECK_COMPILE_FLAG([-Wno-tautological-constant-compare], AX_CHECK_COMPILE_FLAG([-Wno-tautological-constant-compare],
......
...@@ -75,11 +75,14 @@ set(tests ...@@ -75,11 +75,14 @@ set(tests
test_mock_pub_sub) test_mock_pub_sub)
if(NOT WIN32) 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() endif()
if(ZMQ_HAVE_CURVE) if(ZMQ_HAVE_CURVE)
list(APPEND tests test_security_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() endif()
option(ENABLE_CAPSH "Run tests that require sudo and capsh (for cap_net_admin)" OFF) option(ENABLE_CAPSH "Run tests that require sudo and capsh (for cap_net_admin)" OFF)
......
/*
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
/*
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
/*
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
/*
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
/*
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
/*
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_) ...@@ -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_) 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]; char buffer[128];
memset (buffer, 0, sizeof (buffer)); 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)); int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
TEST_ASSERT_EQUAL_INT (64, rc); send (fd_, buffer, sizeof (zmtp_greeting_null), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_greeting_null), rc);
recv_with_retry (fd_, buffer, 64); recv_with_retry (fd_, buffer, sizeof (zmtp_greeting_null));
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};
memset (buffer, 0, sizeof (buffer)); memset (buffer, 0, sizeof (buffer));
memcpy (buffer, zmtp_ready, 43); memcpy (buffer, zmtp_ready_dealer, sizeof (zmtp_ready_dealer));
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 43, 0)); rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
TEST_ASSERT_EQUAL_INT (43, rc); send (fd_, buffer, sizeof (zmtp_ready_dealer), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_dealer), rc);
// greeting // greeting
recv_with_retry (fd_, buffer, 43); recv_with_retry (fd_, buffer, sizeof (zmtp_ready_dealer));
if (mock_ping_) { if (mock_ping_) {
// test PING context - should be replicated in the PONG // test PING context - should be replicated in the PONG
...@@ -226,21 +221,7 @@ static void test_heartbeat_timeout (int server_type_, int mock_ping_) ...@@ -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, prep_server_socket (!mock_ping_, 0, &server, &server_mon, my_endpoint,
MAX_SOCKET_STRING, server_type_); MAX_SOCKET_STRING, server_type_);
struct sockaddr_in ip4addr; fd_t s = connect_socket (my_endpoint);
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);
// Mock a ZMTP 3 client so we can forcibly time out a connection // Mock a ZMTP 3 client so we can forcibly time out a connection
mock_handshake (s, mock_ping_); mock_handshake (s, mock_ping_);
......
...@@ -19,17 +19,6 @@ ...@@ -19,17 +19,6 @@
#include "testutil.hpp" #include "testutil.hpp"
#include "testutil_unity.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 <stdlib.h>
#include <string.h> #include <string.h>
...@@ -67,7 +56,7 @@ static int get_monitor_event (void *monitor_) ...@@ -67,7 +56,7 @@ static int get_monitor_event (void *monitor_)
return -1; 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; int received = 0;
while (true) { while (true) {
...@@ -81,13 +70,11 @@ static void recv_with_retry (raw_socket fd_, char *buffer_, int bytes_) ...@@ -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]; char buffer[128];
memset (buffer, 0, sizeof (buffer)); 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 // Mock ZMTP 3.1 which uses commands
if (sub_command) { if (sub_command) {
...@@ -99,24 +86,20 @@ static void mock_handshake (raw_socket fd_, bool sub_command, bool mock_pub) ...@@ -99,24 +86,20 @@ static void mock_handshake (raw_socket fd_, bool sub_command, bool mock_pub)
recv_with_retry (fd_, buffer, 64); recv_with_retry (fd_, buffer, 64);
if (!mock_pub) { if (!mock_pub) {
const uint8_t zmtp_ready[27] = { rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
4, 25, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e', fd_, (const char *) zmtp_ready_sub, sizeof (zmtp_ready_sub), 0));
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 3, 'S', 'U', 'B'}; TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_sub), rc);
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (fd_, (const char *) zmtp_ready, 27, 0));
TEST_ASSERT_EQUAL_INT (27, rc);
} else { } else {
const uint8_t zmtp_ready[28] = { rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
4, 26, 5, 'R', 'E', 'A', 'D', 'Y', 11, 'S', 'o', 'c', 'k', 'e', fd_, (const char *) zmtp_ready_xpub, sizeof (zmtp_ready_xpub), 0));
't', '-', 'T', 'y', 'p', 'e', 0, 0, 0, 4, 'X', 'P', 'U', 'B'}; TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_xpub), rc);
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (fd_, (const char *) zmtp_ready, 28, 0));
TEST_ASSERT_EQUAL_INT (28, rc);
} }
// greeting - XPUB has one extra byte // greeting - XPUB has one extra byte
memset (buffer, 0, sizeof (buffer)); 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_, static void prep_server_socket (void **server_out_,
...@@ -158,21 +141,7 @@ static void test_mock_pub_sub (bool sub_command_, bool mock_pub_) ...@@ -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, prep_server_socket (&server, &server_mon, my_endpoint, MAX_SOCKET_STRING,
mock_pub_ ? ZMQ_SUB : ZMQ_XPUB); mock_pub_ ? ZMQ_SUB : ZMQ_XPUB);
struct sockaddr_in ip4addr; fd_t s = connect_socket (my_endpoint);
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);
// Mock a ZMTP 3 client so we can forcibly try sub commands // Mock a ZMTP 3 client so we can forcibly try sub commands
mock_handshake (s, sub_command_, mock_pub_); mock_handshake (s, sub_command_, mock_pub_);
......
...@@ -47,17 +47,6 @@ ...@@ -47,17 +47,6 @@
#include "testutil.hpp" #include "testutil.hpp"
#include "testutil_security.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 <unity.h>
#include "../src/tweetnacl.h" #include "../src/tweetnacl.h"
...@@ -223,34 +212,10 @@ void test_curve_security_with_plain_client_credentials () ...@@ -223,34 +212,10 @@ void test_curve_security_with_plain_client_credentials ()
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon); 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 () void test_curve_security_unauthenticated_message ()
{ {
// Unauthenticated messages from a vanilla socket shouldn't be received // 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 anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0); send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received // 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]) ...@@ -277,21 +242,16 @@ template <size_t N> void send (fd_t fd_, const char (&data_)[N])
send_all (fd_, data_, N - 1); 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_all (fd_, reinterpret_cast<const char *> (&data_), N);
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");
} }
void test_curve_security_invalid_hello_wrong_length () 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 (s, zmtp_greeting_curve);
send_greeting (s);
// send CURVE HELLO of wrong size // send CURVE HELLO of wrong size
send (s, "\x04\x06\x05HELLO"); send (s, "\x04\x06\x05HELLO");
...@@ -355,9 +315,9 @@ template <size_t N> void send_command (fd_t s_, char (&command_)[N]) ...@@ -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 () 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 (); zmq::curve_client_tools_t tools = make_curve_client_tools ();
...@@ -377,9 +337,9 @@ void test_curve_security_invalid_hello_command_name () ...@@ -377,9 +337,9 @@ void test_curve_security_invalid_hello_command_name ()
void test_curve_security_invalid_hello_version () 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 (); zmq::curve_client_tools_t tools = make_curve_client_tools ();
...@@ -429,9 +389,9 @@ void recv_greeting (fd_t fd_) ...@@ -429,9 +389,9 @@ void recv_greeting (fd_t fd_)
fd_t connect_exchange_greeting_and_send_hello ( fd_t connect_exchange_greeting_and_send_hello (
char *my_endpoint_, zmq::curve_client_tools_t &tools_) 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); recv_greeting (s);
// send valid CURVE HELLO // send valid CURVE HELLO
......
...@@ -30,17 +30,6 @@ ...@@ -30,17 +30,6 @@
#include "testutil.hpp" #include "testutil.hpp"
#include "testutil_monitoring.hpp" #include "testutil_monitoring.hpp"
#include "testutil_unity.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 <stdlib.h>
#include <string.h> #include <string.h>
...@@ -253,23 +242,7 @@ void test_plain_creds () ...@@ -253,23 +242,7 @@ void test_plain_creds ()
// Unauthenticated messages from a vanilla socket shouldn't be received // Unauthenticated messages from a vanilla socket shouldn't be received
void test_vanilla_socket () void test_vanilla_socket ()
{ {
struct sockaddr_in ip4addr; fd_t s = connect_socket (my_endpoint);
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);
// send anonymous ZMTP/1.0 greeting // send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0); send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received // send sneaky message that shouldn't be received
......
...@@ -169,25 +169,8 @@ void test_vanilla_socket () ...@@ -169,25 +169,8 @@ void test_vanilla_socket ()
char my_endpoint[MAX_SOCKET_STRING]; char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint); bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
struct sockaddr_in ip4addr; fd_t s = connect_socket (my_endpoint);
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);
// send anonymous ZMTP/1.0 greeting // send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0); send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received // send sneaky message that shouldn't be received
......
...@@ -30,18 +30,6 @@ ...@@ -30,18 +30,6 @@
#include "testutil.hpp" #include "testutil.hpp"
#include "testutil_unity.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 <stdlib.h>
#include <string.h> #include <string.h>
...@@ -195,25 +183,7 @@ void test_plain_wrong_credentials_fails () ...@@ -195,25 +183,7 @@ void test_plain_wrong_credentials_fails ()
void test_plain_vanilla_socket () void test_plain_vanilla_socket ()
{ {
// Unauthenticated messages from a vanilla socket shouldn't be received // Unauthenticated messages from a vanilla socket shouldn't be received
struct sockaddr_in ip4addr; fd_t s = connect_socket (my_endpoint);
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);
// send anonymous ZMTP/1.0 greeting // send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0); send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received // send sneaky message that shouldn't be received
......
...@@ -43,12 +43,13 @@ void tearDown () ...@@ -43,12 +43,13 @@ void tearDown ()
#define THREAD_COUNT 100 #define THREAD_COUNT 100
extern "C" { 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. // 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; return NULL;
} }
...@@ -57,7 +58,6 @@ static void *worker (void *s_) ...@@ -57,7 +58,6 @@ static void *worker (void *s_)
void test_shutdown_stress_tipc () void test_shutdown_stress_tipc ()
{ {
void *s1; void *s1;
void *s2;
int i; int i;
int j; int j;
pthread_t threads[THREAD_COUNT]; pthread_t threads[THREAD_COUNT];
...@@ -72,9 +72,8 @@ void test_shutdown_stress_tipc () ...@@ -72,9 +72,8 @@ void test_shutdown_stress_tipc ()
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s1, "tipc://{5560,0,0}")); TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s1, "tipc://{5560,0,0}"));
for (i = 0; i != THREAD_COUNT; i++) { for (i = 0; i != THREAD_COUNT; i++) {
s2 = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_SUCCESS_RAW_ERRNO ( 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++) { for (i = 0; i != THREAD_COUNT; i++) {
......
...@@ -105,21 +105,10 @@ void *setup_socks_server (char *socks_server_address, ...@@ -105,21 +105,10 @@ void *setup_socks_server (char *socks_server_address,
int socks_server_address_len) int socks_server_address_len)
{ {
fprintf (stderr, "socks_server: setup socks server\n"); fprintf (stderr, "socks_server: setup socks server\n");
int server_fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); int server_fd =
TEST_ASSERT_NOT_EQUAL (-1, server_fd); bind_socket_resolve_port ("127.0.0.1", "0", socks_server_address);
int flag = 1; memmove (socks_server_address, strchr (socks_server_address, '/') + 2,
int res; strlen (strchr (socks_server_address, '/') + 1));
#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);
fprintf (stderr, "socks_server: bound to: tcp://%s\n", fprintf (stderr, "socks_server: bound to: tcp://%s\n",
socks_server_address); socks_server_address);
return (void *) (intptr_t) server_fd; return (void *) (intptr_t) server_fd;
......
...@@ -32,12 +32,6 @@ ...@@ -32,12 +32,6 @@
#include <string.h> #include <string.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
SETUP_TEARDOWN_TESTCONTEXT SETUP_TEARDOWN_TESTCONTEXT
void test_stream_exceeds_buffer () void test_stream_exceeds_buffer ()
...@@ -47,16 +41,7 @@ void test_stream_exceeds_buffer () ...@@ -47,16 +41,7 @@ void test_stream_exceeds_buffer ()
unsigned char rcvbuf[msgsize]; unsigned char rcvbuf[msgsize];
char my_endpoint[MAX_SOCKET_STRING]; char my_endpoint[MAX_SOCKET_STRING];
int server_sock = int server_sock = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
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));
void *zsock = test_context_socket (ZMQ_STREAM); void *zsock = test_context_socket (ZMQ_STREAM);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (zsock, my_endpoint)); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (zsock, my_endpoint));
......
...@@ -37,33 +37,12 @@ ...@@ -37,33 +37,12 @@
SETUP_TEARDOWN_TESTCONTEXT SETUP_TEARDOWN_TESTCONTEXT
#if !defined(ZMQ_HAVE_WINDOWS) #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_, void pre_allocate_sock_tcp (void *socket_, char *my_endpoint_)
int af_,
int protocol_,
const sockaddr *addr_,
size_t addr_len_)
{ {
const int s_pre = fd_t s = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint_);
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));
TEST_ASSERT_SUCCESS_ERRNO ( TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (zmq_socket_, ZMQ_USE_FD, &s_pre, sizeof (s_pre))); zmq_setsockopt (socket_, ZMQ_USE_FD, &s, sizeof (s)));
return s_pre;
} }
typedef void (*pre_allocate_sock_fun_t) (void *, char *); 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_) ...@@ -166,41 +145,6 @@ void test_client_server (pre_allocate_sock_fun_t pre_allocate_sock_fun_)
#endif #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 () void test_req_rep_tcp ()
{ {
test_req_rep (pre_allocate_sock_tcp); test_req_rep (pre_allocate_sock_tcp);
...@@ -218,38 +162,14 @@ void test_client_server_tcp () ...@@ -218,38 +162,14 @@ void test_client_server_tcp ()
#endif #endif
} }
void pre_allocate_sock_ipc_int (void *zmq_socket_, const char *path_) char ipc_endpoint[MAX_SOCKET_STRING] = "";
{
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];
void pre_allocate_sock_ipc (void *sb_, char *my_endpoint_) void pre_allocate_sock_ipc (void *sb_, char *my_endpoint_)
{ {
strcpy (ipc_endpoint, "tmpXXXXXX"); fd_t s = bind_socket_resolve_port ("", "", my_endpoint_, AF_UNIX, 0);
TEST_ASSERT_SUCCESS_ERRNO (
#ifdef HAVE_MKDTEMP zmq_setsockopt (sb_, ZMQ_USE_FD, &s, sizeof (s)));
TEST_ASSERT_TRUE (mkdtemp (ipc_endpoint)); strcpy (ipc_endpoint, strchr (my_endpoint_, '/') + 2);
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);
} }
void test_req_rep_ipc () void test_req_rep_ipc ()
...@@ -277,7 +197,7 @@ void test_client_server_ipc () ...@@ -277,7 +197,7 @@ void test_client_server_ipc ()
int main () int main ()
{ {
setup_test_environment (); setup_test_environment (0);
UNITY_BEGIN (); UNITY_BEGIN ();
RUN_TEST (test_req_rep_tcp); RUN_TEST (test_req_rep_tcp);
......
/*
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 @@ ...@@ -35,6 +35,10 @@
#if defined _WIN32 #if defined _WIN32
#include "../src/windows.hpp" #include "../src/windows.hpp"
#if defined _MSC_VER #if defined _MSC_VER
#if defined ZMQ_HAVE_IPC
#include <direct.h>
#include <afunix.h>
#endif
#include <crtdbg.h> #include <crtdbg.h>
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
// iphlpapi is needed for if_nametoindex (not on Windows XP) // iphlpapi is needed for if_nametoindex (not on Windows XP)
...@@ -55,6 +59,7 @@ ...@@ -55,6 +59,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/if.h> #include <net/if.h>
#include <netdb.h> #include <netdb.h>
#include <sys/un.h>
#if defined(ZMQ_HAVE_AIX) #if defined(ZMQ_HAVE_AIX)
#include <sys/types.h> #include <sys/types.h>
#include <sys/socketvar.h> #include <sys/socketvar.h>
...@@ -365,6 +370,147 @@ sockaddr_in bind_bsd_socket (int socket_) ...@@ -365,6 +370,147 @@ sockaddr_in bind_bsd_socket (int socket_)
return saddr; 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_) bool streq (const char *lhs_, const char *rhs_)
{ {
return strcmp (lhs_, rhs_) == 0; return strcmp (lhs_, rhs_) == 0;
......
...@@ -38,6 +38,14 @@ ...@@ -38,6 +38,14 @@
#include "../include/zmq.h" #include "../include/zmq.h"
#include "../src/stdint.hpp" #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 // This defines the settle time used in tests; raise this if we
// get test failures on slower systems due to binds/connects not // get test failures on slower systems due to binds/connects not
// settled. Tested to work reliably at 1 msec on a fast PC. // settled. Tested to work reliably at 1 msec on a fast PC.
...@@ -57,8 +65,33 @@ ...@@ -57,8 +65,33 @@
#define ENDPOINT_5 "udp://127.0.0.1:5560" #define ENDPOINT_5 "udp://127.0.0.1:5560"
#define PORT_6 5561 #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 #undef NDEBUG
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
// duplicated from fd.hpp // duplicated from fd.hpp
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
#ifndef NOMINMAX #ifndef NOMINMAX
...@@ -172,4 +205,20 @@ int test_inet_pton (int af_, const char *src_, void *dst_); ...@@ -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 // Binds an ipv4 BSD socket to an ephemeral port, returns the compiled sockaddr
struct sockaddr_in bind_bsd_socket (int socket); 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 #endif
...@@ -55,12 +55,10 @@ int test_assert_success_message_errno_helper (int rc_, ...@@ -55,12 +55,10 @@ int test_assert_success_message_errno_helper (int rc_,
return rc_; return rc_;
} }
int test_assert_success_message_raw_errno_helper (int rc_, int test_assert_success_message_raw_errno_helper (
const char *msg_, int rc_, const char *msg_, const char *expr_, int line_, bool zero)
const char *expr_,
int line_)
{ {
if (rc_ == -1) { if (rc_ == -1 || (zero && rc_ != 0)) {
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
int current_errno = WSAGetLastError (); int current_errno = WSAGetLastError ();
#else #else
...@@ -70,14 +68,24 @@ int test_assert_success_message_raw_errno_helper (int rc_, ...@@ -70,14 +68,24 @@ int test_assert_success_message_raw_errno_helper (int rc_,
char buffer[512]; char buffer[512];
buffer[sizeof (buffer) - 1] = buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013 0; // to ensure defined behavior with VC++ <= 2013
snprintf (buffer, sizeof (buffer) - 1, "%s failed%s%s%s, errno = %i", snprintf (
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "", buffer, sizeof (buffer) - 1, "%s failed%s%s%s with %d, errno = %i/%s",
msg_ ? ")" : "", current_errno); expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", rc_, current_errno, strerror (current_errno));
UNITY_TEST_FAIL (line_, buffer); UNITY_TEST_FAIL (line_, buffer);
} }
return rc_; 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 test_assert_failure_message_raw_errno_helper (
int rc_, int expected_errno_, const char *msg_, const char *expr_, int line_) 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_, ...@@ -43,10 +43,13 @@ int test_assert_success_message_errno_helper (int rc_,
const char *expr_, const char *expr_,
int line); int line);
int test_assert_success_message_raw_errno_helper (int rc_, int test_assert_success_message_raw_errno_helper (
const char *msg_, int rc_, const char *msg_, const char *expr_, int line, bool zero_ = false);
const char *expr_,
int line); 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 test_assert_failure_message_raw_errno_helper (
int rc_, int expected_errno_, const char *msg_, const char *expr_, int line); 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 ( ...@@ -88,9 +91,22 @@ int test_assert_failure_message_raw_errno_helper (
// A typical use would be: // A typical use would be:
// TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0)); // TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0));
// In case of success, the result of the macro is the result of 'expr'. // 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) \ #define TEST_ASSERT_SUCCESS_RAW_ERRNO(expr) \
test_assert_success_message_raw_errno_helper (expr, NULL, #expr, __LINE__) 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 // 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 // 'error_code'. In case of an unexpected succces, or a failure with an
// unexpected error code, the assertion message includes the literal 'expr' // unexpected error code, the assertion message includes the literal 'expr'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment