From 4c2d11f1792673ed9600364150f4fcf27342cfc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 12 Jul 2024 12:15:20 +0200 Subject: [PATCH] Sync from SUSE:ALP:Source:Standard:1.0 saltbundle-zeromq revision 80012a7967485afb59863a41fc35cf64 --- .gitattributes | 23 + CVE-2019-13132.patch | 110 +++ CVE-2019-6250.patch | 17 + CVE-2020-15166.patch | 328 +++++++++ bsc1176256.patch | 15 + bsc1176257.patch | 12 + bsc1176258.patch | 1308 +++++++++++++++++++++++++++++++++++ bsc1176259.patch | 15 + saltbundle-zeromq-rpmlintrc | 1 + saltbundle-zeromq.changes | 436 ++++++++++++ saltbundle-zeromq.spec | 151 ++++ zeromq-4.2.3.tar.gz | 3 + 12 files changed, 2419 insertions(+) create mode 100644 .gitattributes create mode 100644 CVE-2019-13132.patch create mode 100644 CVE-2019-6250.patch create mode 100644 CVE-2020-15166.patch create mode 100644 bsc1176256.patch create mode 100644 bsc1176257.patch create mode 100644 bsc1176258.patch create mode 100644 bsc1176259.patch create mode 100644 saltbundle-zeromq-rpmlintrc create mode 100644 saltbundle-zeromq.changes create mode 100644 saltbundle-zeromq.spec create mode 100644 zeromq-4.2.3.tar.gz diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fecc750 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/CVE-2019-13132.patch b/CVE-2019-13132.patch new file mode 100644 index 0000000..a35e9eb --- /dev/null +++ b/CVE-2019-13132.patch @@ -0,0 +1,110 @@ +From b2fe2a2c957af991df0d7acc9217f6ed5daf2a38 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Tue, 2 Jul 2019 01:24:19 +0100 +Subject: [PATCH] Problem: application metadata not parsed correctly when using + CURVE + +Solution: create buffers large enough to contain arbitrary metadata +--- + src/curve_server.cpp | 35 ++++++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 11 deletions(-) + +diff --git a/src/curve_server.cpp b/src/curve_server.cpp +index 643e887b..97700dac 100644 +--- a/src/curve_server.cpp ++++ b/src/curve_server.cpp +@@ -326,8 +326,12 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES; + + uint8_t initiate_nonce [crypto_box_NONCEBYTES]; +- uint8_t initiate_plaintext [crypto_box_ZEROBYTES + 128 + 256]; +- uint8_t initiate_box [crypto_box_BOXZEROBYTES + 144 + 256]; ++ uint8_t *initiate_plaintext = ++ static_cast (malloc (crypto_box_ZEROBYTES + clen)); ++ alloc_assert (initiate_plaintext); ++ uint8_t *initiate_box = ++ static_cast (malloc (crypto_box_BOXZEROBYTES + clen)); ++ alloc_assert (initiate_box); + + // Open Box [C + vouch + metadata](C'->S') + memset (initiate_box, 0, crypto_box_BOXZEROBYTES); +@@ -338,6 +342,8 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + memcpy (initiate_nonce + 16, initiate + 105, 8); + cn_peer_nonce = get_uint64(initiate + 105); + ++ const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES; ++ + rc = crypto_box_open (initiate_plaintext, initiate_box, + clen, initiate_nonce, cn_client, cn_secret); + if (rc != 0) { +@@ -345,11 +351,10 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); + errno = EPROTO; +- return -1; ++ rc = -1; ++ goto exit; + } + +- const uint8_t *client_key = initiate_plaintext + crypto_box_ZEROBYTES; +- + uint8_t vouch_nonce [crypto_box_NONCEBYTES]; + uint8_t vouch_plaintext [crypto_box_ZEROBYTES + 64]; + uint8_t vouch_box [crypto_box_BOXZEROBYTES + 80]; +@@ -371,7 +376,8 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); + errno = EPROTO; +- return -1; ++ rc = -1; ++ goto exit; + } + + // What we decrypted must be the client's short-term public key +@@ -383,7 +389,8 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE); + errno = EPROTO; +- return -1; ++ rc = -1; ++ goto exit; + } + + // Precompute connection secret from client key +@@ -405,7 +412,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + // is attempted) + rc = receive_and_process_zap_reply (); + if (rc == -1) +- return -1; ++ goto exit; + } else if (!options.zap_enforce_domain) { + // This supports the Stonehouse pattern (encryption without + // authentication) in legacy mode (domain set but no handler). +@@ -413,15 +420,21 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) + } else { + session->get_socket ()->event_handshake_failed_no_detail ( + session->get_endpoint (), EFAULT); +- return -1; ++ rc = -1; ++ goto exit; + } + } else { + // This supports the Stonehouse pattern (encryption without authentication). + state = sending_ready; + } + +- return parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128, +- clen - crypto_box_ZEROBYTES - 128); ++ rc = parse_metadata (initiate_plaintext + crypto_box_ZEROBYTES + 128, ++ clen - crypto_box_ZEROBYTES - 128); ++ ++exit: ++ free (initiate_plaintext); ++ free (initiate_box); ++ return rc; + } + + int zmq::curve_server_t::produce_ready (msg_t *msg_) +-- +2.20.1 + diff --git a/CVE-2019-6250.patch b/CVE-2019-6250.patch new file mode 100644 index 0000000..d7ddbdf --- /dev/null +++ b/CVE-2019-6250.patch @@ -0,0 +1,17 @@ +Author: Guido Vranken +Description: pointer overflow in zmq::v2_decoder_t::size_ready + leading to remote code execution (issue #3351). + Refactor bounds check arithmetic such that no overflow shall occur +Origin: https://github.com/zeromq/libzmq/pull/3353 +Applied-Upstream: 1a2ed12716693073032d57dac4e269df3d373751 +--- a/src/v2_decoder.cpp ++++ b/src/v2_decoder.cpp +@@ -108,7 +108,7 @@ int zmq::v2_decoder_t::size_ready(uint64_t msg_size, unsigned char const* read_p + // the current message can exceed the current buffer. We have to copy the buffer + // data into a new message and complete it in the next receive. + +- if (unlikely ((unsigned char*)read_pos + msg_size > (data() + size()))) ++ if (unlikely (msg_size > (size_t) (data () + size () - read_pos))) + { + // a new message has started, but the size would exceed the pre-allocated arena + // this happens every time when a message does not fit completely into the buffer diff --git a/CVE-2020-15166.patch b/CVE-2020-15166.patch new file mode 100644 index 0000000..ea8044c --- /dev/null +++ b/CVE-2020-15166.patch @@ -0,0 +1,328 @@ +From 6557497b7095399424fe24e83bd936a3d54d4175 Mon Sep 17 00:00:00 2001 +From: Doron Somech +Date: Wed, 13 May 2020 17:32:06 +0300 +Subject: [PATCH] problem: zeromq connects peer before handshake is completed + +Solution: delay connecting the peer pipe until the handshake is completed +(cherry picked from commit e7f0090b161ce6344f6bd35009816a925c070b09) + +Conflicts: + src/i_engine.hpp + src/norm_engine.hpp + src/pgm_receiver.hpp + src/pgm_sender.hpp + src/raw_engine.cpp + src/session_base.cpp + src/session_base.hpp + src/stream_engine_base.cpp + src/stream_engine_base.hpp + src/udp_engine.hpp + src/ws_engine.cpp + src/zmtp_engine.cpp +--- + src/i_engine.hpp | 4 ++++ + src/ipc_connecter.cpp | 2 +- + src/ipc_listener.cpp | 2 +- + src/norm_engine.hpp | 2 ++ + src/pgm_receiver.hpp | 1 + + src/pgm_sender.hpp | 1 + + src/session_base.cpp | 19 +++++++++++++------ + src/session_base.hpp | 1 + + src/socks_connecter.cpp | 2 +- + src/stream_engine.cpp | 12 ++++++++++-- + src/stream_engine.hpp | 8 +++++++- + src/tcp_connecter.cpp | 2 +- + src/tcp_listener.cpp | 2 +- + src/tipc_connecter.cpp | 2 +- + src/tipc_listener.cpp | 2 +- + src/udp_engine.hpp | 2 ++ + 16 files changed, 48 insertions(+), 16 deletions(-) + +Index: zeromq-4.2.3/src/i_engine.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/i_engine.hpp ++++ zeromq-4.2.3/src/i_engine.hpp +@@ -41,6 +41,10 @@ namespace zmq + { + virtual ~i_engine () {} + ++ // Indicate if the engine has an handshake stage. ++ // If engine has handshake stage, engine must call session.engine_ready when the handshake is complete. ++ virtual bool has_handshake_stage () = 0; ++ + // Plug the engine to the session. + virtual void plug (zmq::io_thread_t *io_thread_, + class session_base_t *session_) = 0; +Index: zeromq-4.2.3/src/ipc_connecter.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/ipc_connecter.cpp ++++ zeromq-4.2.3/src/ipc_connecter.cpp +@@ -123,7 +123,7 @@ void zmq::ipc_connecter_t::out_event () + } + // Create the engine object for this connection. + stream_engine_t *engine = new (std::nothrow) +- stream_engine_t (fd, options, endpoint); ++ stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Attach the engine to the corresponding session object. +Index: zeromq-4.2.3/src/ipc_listener.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/ipc_listener.cpp ++++ zeromq-4.2.3/src/ipc_listener.cpp +@@ -172,7 +172,7 @@ void zmq::ipc_listener_t::in_event () + + // Create the engine object for this connection. + stream_engine_t *engine = new (std::nothrow) +- stream_engine_t (fd, options, endpoint); ++ stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Choose I/O thread to run connecter in. Given that we are already +Index: zeromq-4.2.3/src/norm_engine.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/norm_engine.hpp ++++ zeromq-4.2.3/src/norm_engine.hpp +@@ -27,6 +27,8 @@ namespace zmq + int init(const char* network_, bool send, bool recv); + void shutdown(); + ++ bool has_handshake_stage () { return false; }; ++ + // i_engine interface implementation. + // Plug the engine to the session. + virtual void plug (zmq::io_thread_t *io_thread_, +Index: zeromq-4.2.3/src/pgm_receiver.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/pgm_receiver.hpp ++++ zeromq-4.2.3/src/pgm_receiver.hpp +@@ -58,6 +58,7 @@ namespace zmq + int init (bool udp_encapsulation_, const char *network_); + + // i_engine interface implementation. ++ bool has_handshake_stage () { return false; }; + void plug (zmq::io_thread_t *io_thread_, + zmq::session_base_t *session_); + void terminate (); +Index: zeromq-4.2.3/src/pgm_sender.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/pgm_sender.hpp ++++ zeromq-4.2.3/src/pgm_sender.hpp +@@ -57,6 +57,7 @@ namespace zmq + int init (bool udp_encapsulation_, const char *network_); + + // i_engine interface implementation. ++ bool has_handshake_stage () { return false; }; + void plug (zmq::io_thread_t *io_thread_, + zmq::session_base_t *session_); + void terminate (); +Index: zeromq-4.2.3/src/session_base.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/session_base.cpp ++++ zeromq-4.2.3/src/session_base.cpp +@@ -280,7 +280,8 @@ void zmq::session_base_t::read_activated + } + + if (unlikely (engine == NULL)) { +- pipe->check_read (); ++ if (pipe) ++ pipe->check_read (); + return; + } + +@@ -383,7 +384,18 @@ bool zmq::session_base_t::zap_enabled () + void zmq::session_base_t::process_attach (i_engine *engine_) + { + zmq_assert (engine_ != NULL); ++ zmq_assert (!engine); ++ engine = engine_; ++ ++ if (!engine_->has_handshake_stage ()) ++ engine_ready (); ++ ++ // Plug in the engine. ++ engine->plug (io_thread, this); ++} + ++void zmq::session_base_t::engine_ready () ++{ + // Create the pipe if it does not exist yet. + if (!pipe && !is_terminating ()) { + object_t *parents [2] = {this, socket}; +@@ -412,11 +424,6 @@ void zmq::session_base_t::process_attach + // Ask socket to plug into the remote end of the pipe. + send_bind (socket, pipes [1]); + } +- +- // Plug in the engine. +- zmq_assert (!engine); +- engine = engine_; +- engine->plug (io_thread, this); + } + + void zmq::session_base_t::engine_error ( +Index: zeromq-4.2.3/src/session_base.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/session_base.hpp ++++ zeromq-4.2.3/src/session_base.hpp +@@ -67,6 +67,7 @@ namespace zmq + virtual void reset (); + void flush (); + void engine_error (zmq::stream_engine_t::error_reason_t reason); ++ void engine_ready (); + + // i_pipe_events interface implementation. + void read_activated (zmq::pipe_t *pipe_); +Index: zeromq-4.2.3/src/socks_connecter.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/socks_connecter.cpp ++++ zeromq-4.2.3/src/socks_connecter.cpp +@@ -151,7 +151,7 @@ void zmq::socks_connecter_t::in_event () + else { + // Create the engine object for this connection. + stream_engine_t *engine = new (std::nothrow) +- stream_engine_t (s, options, endpoint); ++ stream_engine_t (s, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Attach the engine to the corresponding session object. +Index: zeromq-4.2.3/src/stream_engine.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/stream_engine.cpp ++++ zeromq-4.2.3/src/stream_engine.cpp +@@ -63,7 +63,8 @@ + #include "wire.hpp" + + zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_, +- const std::string &endpoint_) : ++ const std::string &endpoint_, ++ bool has_handshake_stage_) : + s (fd_), + as_server(false), + handle((handle_t)NULL), +@@ -78,6 +79,7 @@ zmq::stream_engine_t::stream_engine_t (f + greeting_size (v2_greeting_size), + greeting_bytes_read (0), + session (NULL), ++ _has_handshake_stage (has_handshake_stage_), + options (options_), + endpoint (endpoint_), + plugged (false), +@@ -290,9 +292,12 @@ void zmq::stream_engine_t::in_event () + zmq_assert (!io_error); + + // If still handshaking, receive and process the greeting message. +- if (unlikely (handshaking)) ++ if (unlikely (handshaking)) { + if (!handshake ()) + return; ++ else if (mechanism == NULL && _has_handshake_stage) ++ session->engine_ready (); ++ } + + zmq_assert (decoder); + +@@ -839,6 +844,9 @@ void zmq::stream_engine_t::mechanism_rea + has_heartbeat_timer = true; + } + ++ if (_has_handshake_stage) ++ session->engine_ready (); ++ + if (options.recv_routing_id) { + msg_t routing_id; + mechanism->peer_routing_id (&routing_id); +Index: zeromq-4.2.3/src/stream_engine.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/stream_engine.hpp ++++ zeromq-4.2.3/src/stream_engine.hpp +@@ -69,10 +69,12 @@ namespace zmq + }; + + stream_engine_t (fd_t fd_, const options_t &options_, +- const std::string &endpoint); ++ const std::string &endpoint, ++ bool has_handshake_stage); + ~stream_engine_t (); + + // i_engine interface implementation. ++ bool has_handshake_stage () { return _has_handshake_stage; }; + void plug (zmq::io_thread_t *io_thread_, + zmq::session_base_t *session_); + void terminate (); +@@ -176,6 +178,10 @@ namespace zmq + // The session this engine is attached to. + zmq::session_base_t *session; + ++ // Indicate if engine has an handshake stage, if it does, engine must call session.engine_ready ++ // when handshake is completed. ++ bool _has_handshake_stage; ++ + options_t options; + + // String representation of endpoint +Index: zeromq-4.2.3/src/tcp_connecter.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/tcp_connecter.cpp ++++ zeromq-4.2.3/src/tcp_connecter.cpp +@@ -156,7 +156,7 @@ void zmq::tcp_connecter_t::out_event () + + // Create the engine object for this connection. + stream_engine_t *engine = new (std::nothrow) +- stream_engine_t (fd, options, endpoint); ++ stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Attach the engine to the corresponding session object. +Index: zeromq-4.2.3/src/tcp_listener.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/tcp_listener.cpp ++++ zeromq-4.2.3/src/tcp_listener.cpp +@@ -108,7 +108,7 @@ void zmq::tcp_listener_t::in_event () + + // Create the engine object for this connection. + stream_engine_t *engine = new (std::nothrow) +- stream_engine_t (fd, options, endpoint); ++ stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Choose I/O thread to run connecter in. Given that we are already +Index: zeromq-4.2.3/src/tipc_connecter.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/tipc_connecter.cpp ++++ zeromq-4.2.3/src/tipc_connecter.cpp +@@ -123,7 +123,7 @@ void zmq::tipc_connecter_t::out_event () + return; + } + // Create the engine object for this connection. +- stream_engine_t *engine = new (std::nothrow) stream_engine_t (fd, options, endpoint); ++ stream_engine_t *engine = new (std::nothrow) stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Attach the engine to the corresponding session object. +Index: zeromq-4.2.3/src/tipc_listener.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/tipc_listener.cpp ++++ zeromq-4.2.3/src/tipc_listener.cpp +@@ -91,7 +91,7 @@ void zmq::tipc_listener_t::in_event () + } + + // Create the engine object for this connection. +- stream_engine_t *engine = new (std::nothrow) stream_engine_t (fd, options, endpoint); ++ stream_engine_t *engine = new (std::nothrow) stream_engine_t (fd, options, endpoint, !options.raw_socket); + alloc_assert (engine); + + // Choose I/O thread to run connecter in. Given that we are already +Index: zeromq-4.2.3/src/udp_engine.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/udp_engine.hpp ++++ zeromq-4.2.3/src/udp_engine.hpp +@@ -23,6 +23,8 @@ namespace zmq + + int init (address_t *address_, bool send_, bool recv_); + ++ bool has_handshake_stage () { return false; }; ++ + // i_engine interface implementation. + // Plug the engine to the session. + void plug (zmq::io_thread_t *io_thread_, class session_base_t *session_); diff --git a/bsc1176256.patch b/bsc1176256.patch new file mode 100644 index 0000000..82cca9f --- /dev/null +++ b/bsc1176256.patch @@ -0,0 +1,15 @@ +https://github.com/zeromq/libzmq/security/advisories/GHSA-fc3w-qxf5-7hp6 + +Index: zeromq-4.2.3/src/decoder_allocators.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/decoder_allocators.hpp ++++ zeromq-4.2.3/src/decoder_allocators.hpp +@@ -71,7 +71,7 @@ namespace zmq + + void resize (std::size_t new_size) + { +- bufsize = new_size; ++ // bufsize = new_size; + } + private: + std::size_t bufsize; diff --git a/bsc1176257.patch b/bsc1176257.patch new file mode 100644 index 0000000..40a50c0 --- /dev/null +++ b/bsc1176257.patch @@ -0,0 +1,12 @@ +Index: zeromq-4.2.3/src/pipe.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/pipe.cpp ++++ zeromq-4.2.3/src/pipe.cpp +@@ -484,6 +484,7 @@ void zmq::pipe_t::process_delimiter () + if (state == active) + state = delimiter_received; + else { ++ rollback(); + outpipe = NULL; + send_pipe_term_ack (peer); + state = term_ack_sent; diff --git a/bsc1176258.patch b/bsc1176258.patch new file mode 100644 index 0000000..fe20d69 --- /dev/null +++ b/bsc1176258.patch @@ -0,0 +1,1308 @@ +Index: zeromq-4.2.3/src/generic_mtrie.hpp +=================================================================== +--- /dev/null ++++ zeromq-4.2.3/src/generic_mtrie.hpp +@@ -0,0 +1,117 @@ ++/* ++Copyright (c) 2018 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 . ++*/ ++ ++#ifndef __ZMQ_GENERIC_MTRIE_HPP_INCLUDED__ ++#define __ZMQ_GENERIC_MTRIE_HPP_INCLUDED__ ++ ++#include ++#include ++ ++#include "macros.hpp" ++#include "stdint.hpp" ++ ++namespace zmq ++{ ++// Multi-trie (prefix tree). Each node in the trie is a set of pointers. ++template class generic_mtrie_t ++{ ++ public: ++ typedef T value_t; ++ typedef const unsigned char *prefix_t; ++ ++ enum rm_result ++ { ++ not_found, ++ last_value_removed, ++ values_remain ++ }; ++ ++ generic_mtrie_t (); ++ ~generic_mtrie_t (); ++ ++ // Add key to the trie. Returns true iff no entry with the same prefix_ ++ // and size_ existed before. ++ bool add (prefix_t prefix_, size_t size_, value_t *value_); ++ ++ // Remove all entries with a specific value from the trie. ++ // The call_on_uniq_ flag controls if the callback is invoked ++ // when there are no entries left on a prefix only (true) ++ // or on every removal (false). The arg_ argument is passed ++ // through to the callback function. ++ template ++ void rm (value_t *value_, ++ void (*func_) (const unsigned char *data_, size_t size_, Arg arg_), ++ Arg arg_, ++ bool call_on_uniq_); ++ ++ // Removes a specific entry from the trie. ++ // Returns the result of the operation. ++ rm_result rm (prefix_t prefix_, size_t size_, value_t *value_); ++ ++ // Calls a callback function for all matching entries, i.e. any node ++ // corresponding to data_ or a prefix of it. The arg_ argument ++ // is passed through to the callback function. ++ template ++ void match (prefix_t data_, ++ size_t size_, ++ void (*func_) (value_t *value_, Arg arg_), ++ Arg arg_); ++ ++ private: ++ bool is_redundant () const; ++ ++ typedef std::set pipes_t; ++ pipes_t *_pipes; ++ ++ unsigned char _min; ++ unsigned short _count; ++ unsigned short _live_nodes; ++ union _next_t ++ { ++ class generic_mtrie_t *node; ++ class generic_mtrie_t **table; ++ } _next; ++ ++ struct iter ++ { ++ generic_mtrie_t *node; ++ generic_mtrie_t *next_node; ++ prefix_t prefix; ++ size_t size; ++ unsigned short current_child; ++ unsigned char new_min; ++ unsigned char new_max; ++ bool processed_for_removal; ++ }; ++ ++ ZMQ_NON_COPYABLE_NOR_MOVABLE (generic_mtrie_t) ++}; ++} ++ ++#endif +Index: zeromq-4.2.3/src/generic_mtrie_impl.hpp +=================================================================== +--- /dev/null ++++ zeromq-4.2.3/src/generic_mtrie_impl.hpp +@@ -0,0 +1,586 @@ ++/* ++Copyright (c) 2018 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 . ++*/ ++ ++#ifndef __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__ ++#define __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__ ++ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "err.hpp" ++#include "macros.hpp" ++#include "generic_mtrie.hpp" ++ ++namespace zmq ++{ ++template ++generic_mtrie_t::generic_mtrie_t () : ++ _pipes (0), ++ _min (0), ++ _count (0), ++ _live_nodes (0) ++{ ++} ++ ++template generic_mtrie_t::~generic_mtrie_t () ++{ ++ LIBZMQ_DELETE (_pipes); ++ ++ if (_count == 1) { ++ zmq_assert (_next.node); ++ LIBZMQ_DELETE (_next.node); ++ } else if (_count > 1) { ++ for (unsigned short i = 0; i != _count; ++i) { ++ LIBZMQ_DELETE (_next.table[i]); ++ } ++ free (_next.table); ++ } ++} ++ ++template ++bool generic_mtrie_t::add (prefix_t prefix_, size_t size_, value_t *pipe_) ++{ ++ generic_mtrie_t *it = this; ++ ++ while (size_) { ++ const unsigned char c = *prefix_; ++ ++ if (c < it->_min || c >= it->_min + it->_count) { ++ // The character is out of range of currently handled ++ // characters. We have to extend the table. ++ if (!it->_count) { ++ it->_min = c; ++ it->_count = 1; ++ it->_next.node = NULL; ++ } else if (it->_count == 1) { ++ const unsigned char oldc = it->_min; ++ generic_mtrie_t *oldp = it->_next.node; ++ it->_count = (it->_min < c ? c - it->_min : it->_min - c) + 1; ++ it->_next.table = static_cast ( ++ malloc (sizeof (generic_mtrie_t *) * it->_count)); ++ alloc_assert (it->_next.table); ++ for (unsigned short i = 0; i != it->_count; ++i) ++ it->_next.table[i] = 0; ++ it->_min = std::min (it->_min, c); ++ it->_next.table[oldc - it->_min] = oldp; ++ } else if (it->_min < c) { ++ // The new character is above the current character range. ++ const unsigned short old_count = it->_count; ++ it->_count = c - it->_min + 1; ++ it->_next.table = static_cast (realloc ( ++ it->_next.table, sizeof (generic_mtrie_t *) * it->_count)); ++ alloc_assert (it->_next.table); ++ for (unsigned short i = old_count; i != it->_count; i++) ++ it->_next.table[i] = NULL; ++ } else { ++ // The new character is below the current character range. ++ const unsigned short old_count = it->_count; ++ it->_count = (it->_min + old_count) - c; ++ it->_next.table = static_cast (realloc ( ++ it->_next.table, sizeof (generic_mtrie_t *) * it->_count)); ++ alloc_assert (it->_next.table); ++ memmove (it->_next.table + it->_min - c, it->_next.table, ++ old_count * sizeof (generic_mtrie_t *)); ++ for (unsigned short i = 0; i != it->_min - c; i++) ++ it->_next.table[i] = NULL; ++ it->_min = c; ++ } ++ } ++ ++ // If next node does not exist, create one. ++ if (it->_count == 1) { ++ if (!it->_next.node) { ++ it->_next.node = new (std::nothrow) generic_mtrie_t; ++ alloc_assert (it->_next.node); ++ ++(it->_live_nodes); ++ } ++ ++ ++prefix_; ++ --size_; ++ it = it->_next.node; ++ } else { ++ if (!it->_next.table[c - it->_min]) { ++ it->_next.table[c - it->_min] = ++ new (std::nothrow) generic_mtrie_t; ++ alloc_assert (it->_next.table[c - it->_min]); ++ ++(it->_live_nodes); ++ } ++ ++ ++prefix_; ++ --size_; ++ it = it->_next.table[c - it->_min]; ++ } ++ } ++ ++ // We are at the node corresponding to the prefix. We are done. ++ const bool result = !it->_pipes; ++ if (!it->_pipes) { ++ it->_pipes = new (std::nothrow) pipes_t; ++ alloc_assert (it->_pipes); ++ } ++ it->_pipes->insert (pipe_); ++ ++ return result; ++} ++ ++template ++template ++void generic_mtrie_t::rm (value_t *pipe_, ++ void (*func_) (prefix_t data_, ++ size_t size_, ++ Arg arg_), ++ Arg arg_, ++ bool call_on_uniq_) ++{ ++ // This used to be implemented as a non-tail recursive travesal of the trie, ++ // which means remote clients controlled the depth of the recursion and the ++ // stack size. ++ // To simulate the non-tail recursion, with post-recursion changes depending on ++ // the result of the recursive call, a stack is used to re-visit the same node ++ // and operate on it again after children have been visisted. ++ // A boolean is used to record whether the node had already been visited and to ++ // determine if the pre- or post- children visit actions have to be taken. ++ // In the case of a node with (N > 1) children, the node has to be re-visited ++ // N times, in the correct order after each child visit. ++ std::list stack; ++ unsigned char *buff = NULL; ++ size_t maxbuffsize = 0; ++ struct iter it = {this, NULL, NULL, 0, 0, 0, false}; ++ stack.push_back (it); ++ ++ while (!stack.empty ()) { ++ it = stack.back (); ++ stack.pop_back (); ++ ++ if (!it.processed_for_removal) { ++ // Remove the subscription from this node. ++ if (it.node->_pipes && it.node->_pipes->erase (pipe_)) { ++ if (!call_on_uniq_ || it.node->_pipes->empty ()) { ++ func_ (buff, it.size, arg_); ++ } ++ ++ if (it.node->_pipes->empty ()) { ++ LIBZMQ_DELETE (it.node->_pipes); ++ } ++ } ++ ++ // Adjust the buffer. ++ if (it.size >= maxbuffsize) { ++ maxbuffsize = it.size + 256; ++ buff = ++ static_cast (realloc (buff, maxbuffsize)); ++ alloc_assert (buff); ++ } ++ ++ switch (it.node->_count) { ++ case 0: ++ // If there are no subnodes in the trie, we are done with this node ++ // pre-processing. ++ break; ++ case 1: { ++ // If there's one subnode (optimisation). ++ ++ buff[it.size] = it.node->_min; ++ // Mark this node as pre-processed and push it, so that the next ++ // visit after the operation on the child can do the removals. ++ it.processed_for_removal = true; ++ stack.push_back (it); ++ struct iter next = { ++ it.node->_next.node, NULL, NULL, ++it.size, 0, 0, false}; ++ stack.push_back (next); ++ break; ++ } ++ default: { ++ // If there are multiple subnodes. ++ // When first visiting this node, initialize the new_min/max parameters ++ // which will then be used after each child has been processed, on the ++ // post-children iterations. ++ if (it.current_child == 0) { ++ // New min non-null character in the node table after the removal ++ it.new_min = it.node->_min + it.node->_count - 1; ++ // New max non-null character in the node table after the removal ++ it.new_max = it.node->_min; ++ } ++ ++ // Mark this node as pre-processed and push it, so that the next ++ // visit after the operation on the child can do the removals. ++ buff[it.size] = it.node->_min + it.current_child; ++ it.processed_for_removal = true; ++ stack.push_back (it); ++ if (it.node->_next.table[it.current_child]) { ++ struct iter next = { ++ it.node->_next.table[it.current_child], ++ NULL, ++ NULL, ++ it.size + 1, ++ 0, ++ 0, ++ false}; ++ stack.push_back (next); ++ } ++ } ++ } ++ } else { ++ // Reset back for the next time, in case this node doesn't get deleted. ++ // This is done unconditionally, unlike when setting this variable to true. ++ it.processed_for_removal = false; ++ ++ switch (it.node->_count) { ++ case 0: ++ // If there are no subnodes in the trie, we are done with this node ++ // post-processing. ++ break; ++ case 1: ++ // If there's one subnode (optimisation). ++ ++ // Prune the node if it was made redundant by the removal ++ if (it.node->_next.node->is_redundant ()) { ++ LIBZMQ_DELETE (it.node->_next.node); ++ it.node->_count = 0; ++ --it.node->_live_nodes; ++ zmq_assert (it.node->_live_nodes == 0); ++ } ++ break; ++ default: ++ // If there are multiple subnodes. ++ { ++ if (it.node->_next.table[it.current_child]) { ++ // Prune redundant nodes from the mtrie ++ if (it.node->_next.table[it.current_child] ++ ->is_redundant ()) { ++ LIBZMQ_DELETE ( ++ it.node->_next.table[it.current_child]); ++ ++ zmq_assert (it.node->_live_nodes > 0); ++ --it.node->_live_nodes; ++ } else { ++ // The node is not redundant, so it's a candidate for being ++ // the new min/max node. ++ // ++ // We loop through the node array from left to right, so the ++ // first non-null, non-redundant node encountered is the new ++ // minimum index. Conversely, the last non-redundant, non-null ++ // node encountered is the new maximum index. ++ if (it.current_child + it.node->_min ++ < it.new_min) ++ it.new_min = ++ it.current_child + it.node->_min; ++ if (it.current_child + it.node->_min ++ > it.new_max) ++ it.new_max = ++ it.current_child + it.node->_min; ++ } ++ } ++ ++ // If there are more children to visit, push again the current ++ // node, so that pre-processing can happen on the next child. ++ // If we are done, reset the child index so that the ::rm is ++ // fully idempotent. ++ ++it.current_child; ++ if (it.current_child >= it.node->_count) ++ it.current_child = 0; ++ else { ++ stack.push_back (it); ++ continue; ++ } ++ ++ // All children have been visited and removed if needed, and ++ // all pre- and post-visit operations have been carried. ++ // Resize/free the node table if needed. ++ zmq_assert (it.node->_count > 1); ++ ++ // Free the node table if it's no longer used. ++ switch (it.node->_live_nodes) { ++ case 0: ++ free (it.node->_next.table); ++ it.node->_next.table = NULL; ++ it.node->_count = 0; ++ break; ++ case 1: ++ // Compact the node table if possible ++ ++ // If there's only one live node in the table we can ++ // switch to using the more compact single-node ++ // representation ++ zmq_assert (it.new_min == it.new_max); ++ zmq_assert (it.new_min >= it.node->_min); ++ zmq_assert (it.new_min ++ < it.node->_min + it.node->_count); ++ { ++ generic_mtrie_t *node = ++ it.node->_next ++ .table[it.new_min - it.node->_min]; ++ zmq_assert (node); ++ free (it.node->_next.table); ++ it.node->_next.node = node; ++ } ++ it.node->_count = 1; ++ it.node->_min = it.new_min; ++ break; ++ default: ++ if (it.new_min > it.node->_min ++ || it.new_max < it.node->_min ++ + it.node->_count - 1) { ++ zmq_assert (it.new_max - it.new_min + 1 ++ > 1); ++ ++ generic_mtrie_t **old_table = ++ it.node->_next.table; ++ zmq_assert (it.new_min > it.node->_min ++ || it.new_max ++ < it.node->_min ++ + it.node->_count - 1); ++ zmq_assert (it.new_min >= it.node->_min); ++ zmq_assert (it.new_max ++ <= it.node->_min ++ + it.node->_count - 1); ++ zmq_assert (it.new_max - it.new_min + 1 ++ < it.node->_count); ++ ++ it.node->_count = ++ it.new_max - it.new_min + 1; ++ it.node->_next.table = ++ static_cast ( ++ malloc (sizeof (generic_mtrie_t *) ++ * it.node->_count)); ++ alloc_assert (it.node->_next.table); ++ ++ memmove (it.node->_next.table, ++ old_table ++ + (it.new_min - it.node->_min), ++ sizeof (generic_mtrie_t *) ++ * it.node->_count); ++ free (old_table); ++ ++ it.node->_min = it.new_min; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ free (buff); ++} ++ ++template ++typename generic_mtrie_t::rm_result ++generic_mtrie_t::rm (prefix_t prefix_, size_t size_, value_t *pipe_) ++{ ++ // This used to be implemented as a non-tail recursive travesal of the trie, ++ // which means remote clients controlled the depth of the recursion and the ++ // stack size. ++ // To simulate the non-tail recursion, with post-recursion changes depending on ++ // the result of the recursive call, a stack is used to re-visit the same node ++ // and operate on it again after children have been visisted. ++ // A boolean is used to record whether the node had already been visited and to ++ // determine if the pre- or post- children visit actions have to be taken. ++ rm_result ret = not_found; ++ std::list stack; ++ struct iter it = {this, NULL, prefix_, size_, 0, 0, 0, false}; ++ stack.push_back (it); ++ ++ while (!stack.empty ()) { ++ it = stack.back (); ++ stack.pop_back (); ++ ++ if (!it.processed_for_removal) { ++ if (!it.size) { ++ if (!it.node->_pipes) { ++ ret = not_found; ++ continue; ++ } ++ ++ typename pipes_t::size_type erased = ++ it.node->_pipes->erase (pipe_); ++ if (it.node->_pipes->empty ()) { ++ zmq_assert (erased == 1); ++ LIBZMQ_DELETE (it.node->_pipes); ++ ret = last_value_removed; ++ continue; ++ } ++ ++ ret = (erased == 1) ? values_remain : not_found; ++ continue; ++ } ++ ++ it.current_child = *it.prefix; ++ if (!it.node->_count || it.current_child < it.node->_min ++ || it.current_child >= it.node->_min + it.node->_count) { ++ ret = not_found; ++ continue; ++ } ++ ++ it.next_node = ++ it.node->_count == 1 ++ ? it.node->_next.node ++ : it.node->_next.table[it.current_child - it.node->_min]; ++ if (!it.next_node) { ++ ret = not_found; ++ continue; ++ } ++ ++ it.processed_for_removal = true; ++ stack.push_back (it); ++ struct iter next = { ++ it.next_node, NULL, it.prefix + 1, it.size - 1, 0, 0, 0, false}; ++ stack.push_back (next); ++ } else { ++ it.processed_for_removal = false; ++ ++ if (it.next_node->is_redundant ()) { ++ LIBZMQ_DELETE (it.next_node); ++ zmq_assert (it.node->_count > 0); ++ ++ if (it.node->_count == 1) { ++ it.node->_next.node = NULL; ++ it.node->_count = 0; ++ --it.node->_live_nodes; ++ zmq_assert (it.node->_live_nodes == 0); ++ } else { ++ it.node->_next.table[it.current_child - it.node->_min] = 0; ++ zmq_assert (it.node->_live_nodes > 1); ++ --it.node->_live_nodes; ++ ++ // Compact the table if possible ++ if (it.node->_live_nodes == 1) { ++ // If there's only one live node in the table we can ++ // switch to using the more compact single-node ++ // representation ++ unsigned short i; ++ for (i = 0; i < it.node->_count; ++i) ++ if (it.node->_next.table[i]) ++ break; ++ ++ zmq_assert (i < it.node->_count); ++ it.node->_min += i; ++ it.node->_count = 1; ++ generic_mtrie_t *oldp = it.node->_next.table[i]; ++ free (it.node->_next.table); ++ it.node->_next.table = NULL; ++ it.node->_next.node = oldp; ++ } else if (it.current_child == it.node->_min) { ++ // We can compact the table "from the left" ++ unsigned short i; ++ for (i = 1; i < it.node->_count; ++i) ++ if (it.node->_next.table[i]) ++ break; ++ ++ zmq_assert (i < it.node->_count); ++ it.node->_min += i; ++ it.node->_count -= i; ++ generic_mtrie_t **old_table = it.node->_next.table; ++ it.node->_next.table = ++ static_cast (malloc ( ++ sizeof (generic_mtrie_t *) * it.node->_count)); ++ alloc_assert (it.node->_next.table); ++ memmove (it.node->_next.table, old_table + i, ++ sizeof (generic_mtrie_t *) * it.node->_count); ++ free (old_table); ++ } else if (it.current_child ++ == it.node->_min + it.node->_count - 1) { ++ // We can compact the table "from the right" ++ unsigned short i; ++ for (i = 1; i < it.node->_count; ++i) ++ if (it.node->_next.table[it.node->_count - 1 - i]) ++ break; ++ ++ zmq_assert (i < it.node->_count); ++ it.node->_count -= i; ++ generic_mtrie_t **old_table = it.node->_next.table; ++ it.node->_next.table = ++ static_cast (malloc ( ++ sizeof (generic_mtrie_t *) * it.node->_count)); ++ alloc_assert (it.node->_next.table); ++ memmove (it.node->_next.table, old_table, ++ sizeof (generic_mtrie_t *) * it.node->_count); ++ free (old_table); ++ } ++ } ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++template ++template ++void generic_mtrie_t::match (prefix_t data_, ++ size_t size_, ++ void (*func_) (value_t *pipe_, Arg arg_), ++ Arg arg_) ++{ ++ for (generic_mtrie_t *current = this; current; data_++, size_--) { ++ // Signal the pipes attached to this node. ++ if (current->_pipes) { ++ for (typename pipes_t::iterator it = current->_pipes->begin (), ++ end = current->_pipes->end (); ++ it != end; ++it) { ++ func_ (*it, arg_); ++ } ++ } ++ ++ // If we are at the end of the message, there's nothing more to match. ++ if (!size_) ++ break; ++ ++ // If there are no subnodes in the trie, return. ++ if (current->_count == 0) ++ break; ++ ++ if (current->_count == 1) { ++ // If there's one subnode (optimisation). ++ if (data_[0] != current->_min) { ++ break; ++ } ++ current = current->_next.node; ++ } else { ++ // If there are multiple subnodes. ++ if (data_[0] < current->_min ++ || data_[0] >= current->_min + current->_count) { ++ break; ++ } ++ current = current->_next.table[data_[0] - current->_min]; ++ } ++ } ++} ++ ++template bool generic_mtrie_t::is_redundant () const ++{ ++ return !_pipes && _live_nodes == 0; ++} ++} ++ ++ ++#endif +Index: zeromq-4.2.3/src/mtrie.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/mtrie.hpp ++++ zeromq-4.2.3/src/mtrie.hpp +@@ -30,73 +30,23 @@ + #ifndef __ZMQ_MTRIE_HPP_INCLUDED__ + #define __ZMQ_MTRIE_HPP_INCLUDED__ + +-#include +-#include ++#include "generic_mtrie.hpp" + +-#include "stdint.hpp" ++#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER > 1600) ++#define ZMQ_HAS_EXTERN_TEMPLATE 1 ++#else ++#define ZMQ_HAS_EXTERN_TEMPLATE 0 ++#endif + + namespace zmq + { ++class pipe_t; + +- class pipe_t; +- +- // Multi-trie. Each node in the trie is a set of pointers to pipes. +- +- class mtrie_t +- { +- public: +- +- mtrie_t (); +- ~mtrie_t (); +- +- // Add key to the trie. Returns true if it's a new subscription +- // rather than a duplicate. +- bool add (unsigned char *prefix_, size_t size_, zmq::pipe_t *pipe_); +- +- // Remove all subscriptions for a specific peer from the trie. +- // The call_on_uniq_ flag controls if the callback is invoked +- // when there are no subscriptions left on some topics or on +- // every removal. +- void rm (zmq::pipe_t *pipe_, +- void (*func_) (unsigned char *data_, size_t size_, void *arg_), +- void *arg_, bool call_on_uniq_); +- +- // Remove specific subscription from the trie. Return true is it was +- // actually removed rather than de-duplicated. +- bool rm (unsigned char *prefix_, size_t size_, zmq::pipe_t *pipe_); +- +- // Signal all the matching pipes. +- void match (unsigned char *data_, size_t size_, +- void (*func_) (zmq::pipe_t *pipe_, void *arg_), void *arg_); +- +- private: +- +- bool add_helper (unsigned char *prefix_, size_t size_, +- zmq::pipe_t *pipe_); +- void rm_helper (zmq::pipe_t *pipe_, unsigned char **buff_, +- size_t buffsize_, size_t maxbuffsize_, +- void (*func_) (unsigned char *data_, size_t size_, void *arg_), +- void *arg_, bool call_on_uniq_); +- bool rm_helper (unsigned char *prefix_, size_t size_, +- zmq::pipe_t *pipe_); +- bool is_redundant () const; +- +- typedef std::set pipes_t; +- pipes_t *pipes; +- +- unsigned char min; +- unsigned short count; +- unsigned short live_nodes; +- union { +- class mtrie_t *node; +- class mtrie_t **table; +- } next; +- +- mtrie_t (const mtrie_t&); +- const mtrie_t &operator = (const mtrie_t&); +- }; ++#if ZMQ_HAS_EXTERN_TEMPLATE ++extern template class generic_mtrie_t; ++#endif + ++typedef generic_mtrie_t mtrie_t; + } + + #endif +- +Index: zeromq-4.2.3/src/macros.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/macros.hpp ++++ zeromq-4.2.3/src/macros.hpp +@@ -10,3 +10,12 @@ + } + + /******************************************************************************/ ++ ++ ++#define ZMQ_NON_COPYABLE_NOR_MOVABLE(classname) \ ++ public: \ ++ classname (const classname &) = delete; \ ++ classname &operator= (const classname &) = delete; \ ++ classname (classname &&) = delete; \ ++ classname &operator= (classname &&) = delete; ++ +Index: zeromq-4.2.3/src/mtrie.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/mtrie.cpp ++++ zeromq-4.2.3/src/mtrie.cpp +@@ -28,407 +28,10 @@ + */ + + #include "precompiled.hpp" +-#include +- +-#include +-#include +- +-#include "err.hpp" +-#include "pipe.hpp" +-#include "macros.hpp" + #include "mtrie.hpp" ++#include "generic_mtrie_impl.hpp" + +-zmq::mtrie_t::mtrie_t () : +- pipes (0), +- min (0), +- count (0), +- live_nodes (0) +-{ +-} +- +-zmq::mtrie_t::~mtrie_t () +-{ +- LIBZMQ_DELETE(pipes); +- +- if (count == 1) { +- zmq_assert (next.node); +- LIBZMQ_DELETE(next.node); +- } +- else if (count > 1) { +- for (unsigned short i = 0; i != count; ++i) { +- LIBZMQ_DELETE(next.table[i]); +- } +- free (next.table); +- } +-} +- +-bool zmq::mtrie_t::add (unsigned char *prefix_, size_t size_, pipe_t *pipe_) +-{ +- return add_helper (prefix_, size_, pipe_); +-} +- +-bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_, +- pipe_t *pipe_) +-{ +- // We are at the node corresponding to the prefix. We are done. +- if (!size_) { +- bool result = !pipes; +- if (!pipes) { +- pipes = new (std::nothrow) pipes_t; +- alloc_assert (pipes); +- } +- pipes->insert (pipe_); +- return result; +- } +- +- unsigned char c = *prefix_; +- if (c < min || c >= min + count) { +- +- // The character is out of range of currently handled +- // characters. We have to extend the table. +- if (!count) { +- min = c; +- count = 1; +- next.node = NULL; +- } +- else +- if (count == 1) { +- unsigned char oldc = min; +- mtrie_t *oldp = next.node; +- count = (min < c ? c - min : min - c) + 1; +- next.table = (mtrie_t**) +- malloc (sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- for (unsigned short i = 0; i != count; ++i) +- next.table [i] = 0; +- min = std::min (min, c); +- next.table [oldc - min] = oldp; +- } +- else +- if (min < c) { +- // The new character is above the current character range. +- unsigned short old_count = count; +- count = c - min + 1; +- next.table = (mtrie_t**) realloc (next.table, +- sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- for (unsigned short i = old_count; i != count; i++) +- next.table [i] = NULL; +- } +- else { +- // The new character is below the current character range. +- unsigned short old_count = count; +- count = (min + old_count) - c; +- next.table = (mtrie_t**) realloc (next.table, +- sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- memmove (next.table + min - c, next.table, +- old_count * sizeof (mtrie_t*)); +- for (unsigned short i = 0; i != min - c; i++) +- next.table [i] = NULL; +- min = c; +- } +- } +- +- // If next node does not exist, create one. +- if (count == 1) { +- if (!next.node) { +- next.node = new (std::nothrow) mtrie_t; +- alloc_assert (next.node); +- ++live_nodes; +- } +- return next.node->add_helper (prefix_ + 1, size_ - 1, pipe_); +- } +- else { +- if (!next.table [c - min]) { +- next.table [c - min] = new (std::nothrow) mtrie_t; +- alloc_assert (next.table [c - min]); +- ++live_nodes; +- } +- return next.table [c - min]->add_helper (prefix_ + 1, size_ - 1, pipe_); +- } +-} +- +- +-void zmq::mtrie_t::rm (pipe_t *pipe_, +- void (*func_) (unsigned char *data_, size_t size_, void *arg_), +- void *arg_, bool call_on_uniq_) +-{ +- unsigned char *buff = NULL; +- rm_helper (pipe_, &buff, 0, 0, func_, arg_, call_on_uniq_); +- free (buff); +-} +- +-void zmq::mtrie_t::rm_helper (pipe_t *pipe_, unsigned char **buff_, +- size_t buffsize_, size_t maxbuffsize_, +- void (*func_) (unsigned char *data_, size_t size_, void *arg_), +- void *arg_, bool call_on_uniq_) +-{ +- // Remove the subscription from this node. +- if (pipes && pipes->erase (pipe_)) { +- if (!call_on_uniq_ || pipes->empty ()) { +- func_ (*buff_, buffsize_, arg_); +- } +- +- if (pipes->empty ()) { +- LIBZMQ_DELETE(pipes); +- } +- } +- +- // Adjust the buffer. +- if (buffsize_ >= maxbuffsize_) { +- maxbuffsize_ = buffsize_ + 256; +- *buff_ = (unsigned char*) realloc (*buff_, maxbuffsize_); +- alloc_assert (*buff_); +- } +- +- // If there are no subnodes in the trie, return. +- if (count == 0) +- return; +- +- // If there's one subnode (optimisation). +- if (count == 1) { +- (*buff_) [buffsize_] = min; +- buffsize_++; +- next.node->rm_helper (pipe_, buff_, buffsize_, maxbuffsize_, +- func_, arg_, call_on_uniq_); +- +- // Prune the node if it was made redundant by the removal +- if (next.node->is_redundant ()) { +- LIBZMQ_DELETE(next.node); +- count = 0; +- --live_nodes; +- zmq_assert (live_nodes == 0); +- } +- return; +- } +- +- // If there are multiple subnodes. +- // +- // New min non-null character in the node table after the removal +- unsigned char new_min = min + count - 1; +- // New max non-null character in the node table after the removal +- unsigned char new_max = min; +- for (unsigned short c = 0; c != count; c++) { +- (*buff_) [buffsize_] = min + c; +- if (next.table [c]) { +- next.table [c]->rm_helper (pipe_, buff_, buffsize_ + 1, +- maxbuffsize_, func_, arg_, call_on_uniq_); +- +- // Prune redundant nodes from the mtrie +- if (next.table [c]->is_redundant ()) { +- LIBZMQ_DELETE(next.table[c]); +- +- zmq_assert (live_nodes > 0); +- --live_nodes; +- } +- else { +- // The node is not redundant, so it's a candidate for being +- // the new min/max node. +- // +- // We loop through the node array from left to right, so the +- // first non-null, non-redundant node encountered is the new +- // minimum index. Conversely, the last non-redundant, non-null +- // node encountered is the new maximum index. +- if (c + min < new_min) +- new_min = c + min; +- if (c + min > new_max) +- new_max = c + min; +- } +- } +- } +- +- zmq_assert (count > 1); +- +- // Free the node table if it's no longer used. +- if (live_nodes == 0) { +- free (next.table); +- next.table = NULL; +- count = 0; +- } +- // Compact the node table if possible +- else +- if (live_nodes == 1) { +- // If there's only one live node in the table we can +- // switch to using the more compact single-node +- // representation +- zmq_assert (new_min == new_max); +- zmq_assert (new_min >= min && new_min < min + count); +- mtrie_t *node = next.table [new_min - min]; +- zmq_assert (node); +- free (next.table); +- next.node = node; +- count = 1; +- min = new_min; +- } +- else +- if (new_min > min || new_max < min + count - 1) { +- zmq_assert (new_max - new_min + 1 > 1); +- +- mtrie_t **old_table = next.table; +- zmq_assert (new_min > min || new_max < min + count - 1); +- zmq_assert (new_min >= min); +- zmq_assert (new_max <= min + count - 1); +- zmq_assert (new_max - new_min + 1 < count); +- +- count = new_max - new_min + 1; +- next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- +- memmove (next.table, old_table + (new_min - min), +- sizeof (mtrie_t*) * count); +- free (old_table); +- +- min = new_min; +- } +-} +- +-bool zmq::mtrie_t::rm (unsigned char *prefix_, size_t size_, pipe_t *pipe_) +-{ +- return rm_helper (prefix_, size_, pipe_); +-} +- +-bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_, +- pipe_t *pipe_) +-{ +- if (!size_) { +- if (pipes) { +- pipes_t::size_type erased = pipes->erase (pipe_); +- zmq_assert (erased == 1); +- if (pipes->empty ()) { +- LIBZMQ_DELETE(pipes); +- } +- } +- return !pipes; +- } +- +- unsigned char c = *prefix_; +- if (!count || c < min || c >= min + count) +- return false; +- +- mtrie_t *next_node = +- count == 1 ? next.node : next.table [c - min]; +- +- if (!next_node) +- return false; +- +- bool ret = next_node->rm_helper (prefix_ + 1, size_ - 1, pipe_); +- +- if (next_node->is_redundant ()) { +- LIBZMQ_DELETE(next_node); +- zmq_assert (count > 0); +- +- if (count == 1) { +- next.node = 0; +- count = 0; +- --live_nodes; +- zmq_assert (live_nodes == 0); +- } +- else { +- next.table [c - min] = 0; +- zmq_assert (live_nodes > 1); +- --live_nodes; +- +- // Compact the table if possible +- if (live_nodes == 1) { +- // If there's only one live node in the table we can +- // switch to using the more compact single-node +- // representation +- unsigned short i; +- for (i = 0; i < count; ++i) +- if (next.table [i]) +- break; +- +- zmq_assert (i < count); +- min += i; +- count = 1; +- mtrie_t *oldp = next.table [i]; +- free (next.table); +- next.node = oldp; +- } +- else +- if (c == min) { +- // We can compact the table "from the left" +- unsigned short i; +- for (i = 1; i < count; ++i) +- if (next.table [i]) +- break; +- +- zmq_assert (i < count); +- min += i; +- count -= i; +- mtrie_t **old_table = next.table; +- next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- memmove (next.table, old_table + i, sizeof (mtrie_t*) * count); +- free (old_table); +- } +- else +- if (c == min + count - 1) { +- // We can compact the table "from the right" +- unsigned short i; +- for (i = 1; i < count; ++i) +- if (next.table [count - 1 - i]) +- break; +- +- zmq_assert (i < count); +- count -= i; +- mtrie_t **old_table = next.table; +- next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count); +- alloc_assert (next.table); +- memmove (next.table, old_table, sizeof (mtrie_t*) * count); +- free (old_table); +- } +- } +- } +- +- return ret; +-} +- +-void zmq::mtrie_t::match (unsigned char *data_, size_t size_, +- void (*func_) (pipe_t *pipe_, void *arg_), void *arg_) +-{ +- mtrie_t *current = this; +- while (true) { +- +- // Signal the pipes attached to this node. +- if (current->pipes) { +- for (pipes_t::iterator it = current->pipes->begin (); +- it != current->pipes->end (); ++it) +- func_ (*it, arg_); +- } +- +- // If we are at the end of the message, there's nothing more to match. +- if (!size_) +- break; +- +- // If there are no subnodes in the trie, return. +- if (current->count == 0) +- break; +- +- // If there's one subnode (optimisation). +- if (current->count == 1) { +- if (data_ [0] != current->min) +- break; +- current = current->next.node; +- data_++; +- size_--; +- continue; +- } +- +- // If there are multiple subnodes. +- if (data_ [0] < current->min || data_ [0] >= +- current->min + current->count) +- break; +- if (!current->next.table [data_ [0] - current->min]) +- break; +- current = current->next.table [data_ [0] - current->min]; +- data_++; +- size_--; +- } +-} +- +-bool zmq::mtrie_t::is_redundant () const ++namespace zmq + { +- return !pipes && live_nodes == 0; ++template class generic_mtrie_t; + } +Index: zeromq-4.2.3/src/xpub.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/xpub.cpp ++++ zeromq-4.2.3/src/xpub.cpp +@@ -35,6 +35,7 @@ + #include "err.hpp" + #include "msg.hpp" + #include "macros.hpp" ++#include "generic_mtrie_impl.hpp" + + zmq::xpub_t::xpub_t (class ctx_t *parent_, uint32_t tid_, int sid_) : + socket_base_t (parent_, tid_, sid_), +@@ -205,7 +206,7 @@ int zmq::xpub_t::xsetsockopt (int option + return 0; + } + +-static void stub (unsigned char *data_, size_t size_, void *arg_) ++static void stub (zmq::mtrie_t::prefix_t data_, size_t size_, void *arg_) + { + LIBZMQ_UNUSED(data_); + LIBZMQ_UNUSED(size_); +@@ -222,7 +223,7 @@ void zmq::xpub_t::xpipe_terminated (pipe + // Remove pipe without actually sending the message as it was taken + // care of by the manual call above. subscriptions is the real mtrie, + // so the pipe must be removed from there or it will be left over. +- subscriptions.rm (pipe_, stub, NULL, false); ++ subscriptions.rm (pipe_, stub, static_cast(NULL), false); + } + else + { +@@ -235,9 +236,8 @@ void zmq::xpub_t::xpipe_terminated (pipe + dist.pipe_terminated (pipe_); + } + +-void zmq::xpub_t::mark_as_matching (pipe_t *pipe_, void *arg_) ++void zmq::xpub_t::mark_as_matching (pipe_t *pipe_, xpub_t *self) + { +- xpub_t *self = (xpub_t*) arg_; + self->dist.match (pipe_); + } + +@@ -317,11 +317,9 @@ bool zmq::xpub_t::xhas_in () + return !pending_data.empty (); + } + +-void zmq::xpub_t::send_unsubscription (unsigned char *data_, size_t size_, +- void *arg_) ++void zmq::xpub_t::send_unsubscription (zmq::mtrie_t::prefix_t data_, size_t size_, ++ xpub_t *self) + { +- xpub_t *self = (xpub_t*) arg_; +- + if (self->options.type != ZMQ_PUB) { + // Place the unsubscription to the queue of pending (un)subscriptions + // to be retrieved by the user later on. +Index: zeromq-4.2.3/src/xpub.hpp +=================================================================== +--- zeromq-4.2.3.orig/src/xpub.hpp ++++ zeromq-4.2.3/src/xpub.hpp +@@ -70,11 +70,11 @@ namespace zmq + + // Function to be applied to the trie to send all the subscriptions + // upstream. +- static void send_unsubscription (unsigned char *data_, size_t size_, +- void *arg_); ++ static void send_unsubscription (zmq::mtrie_t::prefix_t data_, size_t size_, ++ xpub_t *self); + + // Function to be applied to each matching pipes. +- static void mark_as_matching (zmq::pipe_t *pipe_, void *arg_); ++ static void mark_as_matching (zmq::pipe_t *pipe_, xpub_t *arg_); + + // List of all subscriptions mapped to corresponding pipes. + mtrie_t subscriptions; diff --git a/bsc1176259.patch b/bsc1176259.patch new file mode 100644 index 0000000..1a99a3d --- /dev/null +++ b/bsc1176259.patch @@ -0,0 +1,15 @@ +Index: zeromq-4.2.3/src/xpub.cpp +=================================================================== +--- zeromq-4.2.3.orig/src/xpub.cpp ++++ zeromq-4.2.3/src/xpub.cpp +@@ -129,8 +136,9 @@ void zmq::xpub_t::xread_activated (pipe_ + } + } + } +- else { ++ else if (options.type != ZMQ_PUB) { + // Process user message coming upstream from xsub socket ++ // but not if the type is PUB, which never processes user messages + pending_data.push_back (blob_t (data, size)); + if (metadata) + metadata->add_ref (); diff --git a/saltbundle-zeromq-rpmlintrc b/saltbundle-zeromq-rpmlintrc new file mode 100644 index 0000000..2e5673a --- /dev/null +++ b/saltbundle-zeromq-rpmlintrc @@ -0,0 +1 @@ +addFilter('shlib-policy-name-error') diff --git a/saltbundle-zeromq.changes b/saltbundle-zeromq.changes new file mode 100644 index 0000000..84766e6 --- /dev/null +++ b/saltbundle-zeromq.changes @@ -0,0 +1,436 @@ +------------------------------------------------------------------- +Fri Mar 8 11:08:55 UTC 2024 - Victor Zhestkov + +- Make the package building on SLE11 with gcc 4.8. + +------------------------------------------------------------------- +Wed Aug 2 10:16:47 UTC 2023 - Victor Zhestkov + +- Adding missing file reference: + * saltbundle-zeromq-rpmlintrc + +------------------------------------------------------------------- +Mon Aug 15 14:00:46 UTC 2022 - Dirk Müller + +- drop xmlto buildrequires, these are only needed + for non-release builds which do not ship with prebuilt docs + +------------------------------------------------------------------- +Fri Jun 17 06:59:23 UTC 2022 - Victor Zhestkov + +- Disable automatic dependency processing to prevent redundant requires + +------------------------------------------------------------------- +Thu Jan 20 07:25:31 UTC 2022 - Victor Zhestkov + +- Remove baselibs.conf from the sources + +- Removed: + * baselibs.conf + +------------------------------------------------------------------- +Fri Oct 2 13:50:26 UTC 2020 - Adam Majer + +- bsc1176256.patch: fix heap overflow when receiving malformed + ZMTP v1 packets (bsc#1176256) +- bsc1176257.patch: fixes a memory leak in client induced by + malicious server(s) without CURVE/ZAP (bsc#1176257) +- bsc1176259.patch: fix memory leak when processing PUB messages + with metadata (bsc#1176259) +- bsc1176258.patch: fix stack overflow in PUB/XPUB subscription + store (bsc#1176258) + +------------------------------------------------------------------- +Mon Sep 7 11:08:00 UTC 2020 - Adam Majer + +- CVE-2020-15166.patch: fix the possibility of unauthenticated + clients causing a denial-of-service (bsc#1176116, CVE-2020-15166) + +------------------------------------------------------------------- +Wed Jul 3 13:40:37 UTC 2019 - Vítězslav Čížek + +- CVE-2019-13132.patch: Fix an unauthenticated remote code execution + due to a stack overflow on the server (bsc#1140255, CVE-2019-13132) + +------------------------------------------------------------------- +Thu Jan 17 16:31:24 UTC 2019 - astieger@suse.com + +- mark license files using %license macro (bsc#1082318) + +------------------------------------------------------------------- +Mon Jan 14 09:58:57 UTC 2019 - adam.majer@suse.de + +- CVE-2019-6250.patch: fix a remote execution vulnerability due to + pointer arithmetic overflow (bsc#1121717, CVE-2019-6250) + +------------------------------------------------------------------- +Tue Jul 10 11:54:56 UTC 2018 - dimstar@opensuse.org + +- Add baselibs.conf: build libzmq5-32bit, as it is a required + dependency to libavfilter7-32bit (i.e ffmpeg 4). + +------------------------------------------------------------------- +Thu Dec 14 08:00:12 UTC 2017 - adam.majer@suse.de + +- New upstream version 4.2.3 + * API change: previously ZMQ_POLLOUT on a ZMQ_ROUTER socket + returned always true due to how the type works. When + ZMQ_ROUTER_MANDATORY is set, sending fails when the peer is + not available, but ZMQ_POLLOUT always returns true anyway, + which does not make sense. Now when ZMQ_ROUTER_MANDATORY is + set, ZMQ_POLLOUT on a ZMQ_ROUTER will return true only if + at least one peer is available. + Given ZMQ_POLLOUT with ZMQ_ROUTER was not usable at all + previously, we do not consider this a breakage warranting a + major or minor version increase. + * ZMQ_IDENTITY has been renamed to ZMQ_ROUTING_ID and + ZMQ_CONNECT_RID has been renamed to ZMQ_CONNTECT_ROUTING_ID + to disambiguate. ZMQ_IDENTITY and ZMQ_CONNECT_RID are still + available to keep backward compatibility, and will be + removed in a future release after further advance notice. + * DRAFT API change: zmq_poller_wait, zmq_poller_wait_all and + zmq_poller_poll have been changed to be inline with other + existing APIs that have a timeout to return EAGAIN instead + of ETIMEDOUT as the errno value. + * Existing non-DRAFT socket types ZMQ_REP/REQ, ZMQ_ROUTER/DEALER + and ZMQPUB/SUB, that were previously declared deprecated, have + been reinstated as stable and supported + * Curve: all remaining traces of debug output to console are now + removed, and new DRAFT events are available to properly debug + CURVE, PLAIN, GSSAPI and ZAP events and failures. + * for compelete changelog see + https://github.com/zeromq/libzmq/releases/tag/v4.2.3 +- drop remove_werror.patch: can now be disabled at configure time, + if needed. + +------------------------------------------------------------------- +Thu Jun 1 11:25:58 UTC 2017 - adam.majer@suse.de + +- remove_werror.patch: don't use -Werror in compiler flags +- disable silent compilation flags + +------------------------------------------------------------------- +Tue Mar 21 14:30:10 UTC 2017 - adam.majer@suse.de + +- New upstream version 4.2.2 + * fix SO_NOSIGPIPE and connection closing by peer race condition + * fix IPv4-in-IPv6 mapped addresses parsing error + * zmq_z85_decode did validate its input. The function has been + fixed to correctly follow RFC32 and return NULL if the input is + invalid. + * for complete changelog see + https://github.com/zeromq/libzmq/releases/tag/v4.2.2 + +------------------------------------------------------------------- +Fri Feb 3 17:06:33 UTC 2017 - jengelh@inai.de + +- Compact the descriptions. + +------------------------------------------------------------------- +Sat Dec 31 23:53:21 UTC 2016 - adam.majer@suse.de + +- New upstream version 4.2.1 + * Bugfix release. For complete changelog see + https://github.com/zeromq/libzmq/releases/tag/v4.2.1 + +------------------------------------------------------------------- +Sat Nov 5 08:06:42 UTC 2016 - mvyskocil@opensuse.org + +- New upstream version 4.2.0 + * For Pieter. Thanks for making all of this possible. + * This release introduces new APIs, but it is ABI compatible with + libzmq 4.1.2 and up. + * Fixed alignment problem on arm and sparc, need to rebuild + against 4.2.0 + * New Context option ZMQ_MAX_MSGSZ + * New Socket options: + - ZMQ_HANDSHAKE_IVL + - ZMQ_SOCKS_PROXY + - ZMQ_XPUB_NODROP + - ZMQ_BLOCKY + - ZMQ_XPUB_MANUAL + - ZMQ_XPUB_WELCOME_MSG + - ZMQ_STREAM_NOTIFY + - ZMQ_INVERT_MATCHING + - ZMQ_HEARTBEAT_IVL + - ZMQ_HEARTBEAT_TTL + - ZMQ_HEARTBEAT_TIMEOUT + .... + * see NEWS for all changes +- Packaging + * add --with-libsodium to link against libsodium and not internal + tweetnacl + * remove disable-silent-rules + * add --enable-curve to build curve_keygen tool + https://github.com/zeromq/libzmq/pull/2195 + * add libunwind to build dependencies + +------------------------------------------------------------------- +Wed Jun 29 12:28:33 UTC 2016 - jengelh@inai.de + +- Remove useless --with-pic, it's only for (non-built) static libs + +------------------------------------------------------------------- +Tue Jun 28 15:30:44 UTC 2016 - dmueller@suse.com + +- skip testsuite on qemu-linux-user + +------------------------------------------------------------------- +Fri Jun 17 12:41:46 UTC 2016 - adam.majer@suse.de + +- New upstream version 4.1.5 + * Fixed #1806 - uninitialised read in curve getsockopt. + * Fixed #1807 - build broken with GCC 6. + * Fixed #1831 - potential assertion failure with latest libsodium. + * Fixed #1850 - detection issues with tweetnacl/libsodium. + * Fixed #1877 - Avoid terminating connections prematurely + * fixes some IPv6 related issues +- Removed 3ad076.patch, upstreamed + +------------------------------------------------------------------- +Mon May 30 10:02:29 UTC 2016 - adam.majer@suse.de + +- Added patch 3ad076.patch + * based on https://github.com/zeromq/zeromq4-1/commit/3ad076.patch + * refreshed and removed NEWS section + * fixes unbinding when IPv6 is available +- Add '--disable-dependency-tracking' since we are not rebuilding +- Re-enable concurrent check target, but fall back to sequential on + failure. This allows quick test building, while allows + sequential unit test run. Run tests 3x before 'official' failure as + some are a little flaky (upstream acknowledges this) + +------------------------------------------------------------------- +Mon May 30 09:23:12 UTC 2016 - adam.majer@suse.de + +- Append test_log in build output if there are failures + +------------------------------------------------------------------- +Mon May 30 08:42:24 UTC 2016 - adam.majer@suse.de + +- Update to 4.1.4 + * fixed build failure with latest libsodium + * handle IPv6 link local addresses + * fixed assertion failure in msg.cpp:390 on STREAM sockets + * fixed assertion failure in tcp.cpp after network reconnect + * fixed socket monitor hang +- Remove libsodium-init.patch - upstreamed +- Run %check rule sequentially to prevent assert failures + +------------------------------------------------------------------- +Thu Nov 5 09:36:36 UTC 2015 - idonmez@suse.com + +- Add libsodium-init.patch to handle sodium_init() error. + +------------------------------------------------------------------- +Tue Oct 6 11:26:39 UTC 2015 - idonmez@suse.com + +- Re-enable %check + +------------------------------------------------------------------- +Mon Sep 28 14:27:30 UTC 2015 - stephan.barth@suse.com + +- update to version 4.1.3. + Changes from upstream: + * Fixed #1532 - getsockopt ZMQ_RCVMORE now resets all bits instead of only + 32 + * Fixed #1445 - zmq::socket_base_t::connect fails on tcp ipv6 address + +------------------------------------------------------------------- +Tue Sep 22 13:26:21 UTC 2015 - tampakrap@opensuse.org + +- Fix the conditionals on the previous commit + +------------------------------------------------------------------- +Tue Sep 22 12:48:38 UTC 2015 - tampakrap@opensuse.org + +- Conditionally use the pkgconfig style, to support SLE11 + +------------------------------------------------------------------- +Tue Jul 14 08:36:14 UTC 2015 - tchvatal@suse.com + +- Version bump to 4.1.2 bnc#937912: + * Added explicit reference to static link exception in every source file. + * Bumped ABI version to 5:0:0 since 4.1.x changed the ABI. + * Fixed STDINT event interface macros to work with CZMQ 3.0. + * Fixed installation of man pages when BUILD_DOC is not set. + * Fixed #1428 - regression on single-socket proxies. + +------------------------------------------------------------------- +Tue Jun 16 06:03:45 UTC 2015 - mvyskocil@opensuse.org + +- Add pkgconfig(libsodium) as mandatory build dependency +- Change libuuid-devel to pkgconfig style + +------------------------------------------------------------------- +Mon Jun 8 09:11:11 UTC 2015 - mvyskocil@opensuse.org + +- Build depends on openpgm-devel + +------------------------------------------------------------------- +Sun Jun 7 16:53:26 UTC 2015 - mvyskocil@opensuse.org + +- Update to 4.1.1, bugfix release +- drop unecessary + zeromq_4.0.5_avoid_curve_test_hang_on_ppc64.patch + +------------------------------------------------------------------- +Wed Jan 28 14:26:13 UTC 2015 - normand@linux.vnet.ibm.com + +- Add a zeromq_4.0.5_avoid_curve_test_hang_on_ppc64.patch + to avoid curve test to hang for ppc ppc64 ppc64le architectures + related bug ref: bnc#912460 + This is a set of commits grab from zeromq4-x git tree + from https://github.com/zeromq/zeromq4-x.git + Merge pull request #101 from hintjens/master + Problem: issue #1273, protocol downgrade attack + Merge pull request #100 from hintjens/master + Problem: zmq_ctx_term has insane behavior by default + * Also fixes bnc#931978 CVE-2014-9721 + +------------------------------------------------------------------- +Fri Nov 28 11:40:21 UTC 2014 - tchvatal@suse.com + +- Split the curve-keygen binary to separate subpkg bnc#907584 + * Add conflicts to new supackage + +------------------------------------------------------------------- +Thu Nov 13 08:16:06 UTC 2014 - tchvatal@suse.com + +- Gracely continue when checks fail + +------------------------------------------------------------------- +Thu Oct 16 08:40:27 UTC 2014 - tchvatal@suse.com + +- Remove sle11 support, not really needed for us here +- Add libsodium dep for testsuite where possible +- Version bump to 4.0.5 fixes bnc#898917 CVE-2014-7202 and + CVE-2014-7203: + * Fixed #1191; CURVE mechanism does not verify short term nonces. + * Fixed #1190; stream_engine is vulnerable to downgrade attacks. + * Fixed #1088; assertion failure for WSAENOTSOCK on Windows. + * Fixed #1015; race condition while connecting inproc sockets. + * Fixed #994; bump so library number to 4.0.0 + * Fixed #939, assertion failed: !more (fq.cpp:99) after many ZAP requests. + * Fixed #872; lost first part of message over inproc://. + * Fixed #797, keep-alive on Windows. + +------------------------------------------------------------------- +Mon May 12 09:23:17 UTC 2014 - tchvatal@suse.com + +- Cleanup to remove SLE10 and older mentions +- Remove other distros from rules as we don't build for them anyway. +- Cleanup with spec-cleaner. +- Enable tests. + +------------------------------------------------------------------- +Thu Mar 27 13:42:35 UTC 2014 - speilicke@suse.com + +- Move to 'download_files' source service which is in better shap + and easier to use + +------------------------------------------------------------------- +Thu Mar 27 13:36:48 UTC 2014 - mvyskocil@opensuse.org + +- Update to 4.0.4 + For details see /usr/share/doc/packages/zeromq-devel/NEWS +- Moved most of docs to devel package to reduce a size of libmq3 + +------------------------------------------------------------------- +Fri Dec 13 07:09:00 UTC 2013 - bahid@emc.com + +- Update to version 4.0.3 + For details see /usr/share/doc/packages/libzmq3/NEWS + +------------------------------------------------------------------- +Sat Sep 21 15:16:59 UTC 2013 - p.drouand@gmail.com + +- Update to version 3.2.4 + For details see /usr/share/doc/packages/libzmq3/NEWS + +------------------------------------------------------------------- +Fri Nov 23 14:53:09 UTC 2012 - mrueckert@suse.de + +- Update to version 3.2.2 + For details see /usr/share/doc/packages/libzmq3/NEWS + +------------------------------------------------------------------- +Sat Jan 28 21:36:20 UTC 2012 - jengelh@medozas.de + +- Remove redundant tags/sections per specfile guideline suggestions + +------------------------------------------------------------------- +Wed Sep 28 07:04:21 UTC 2011 - saschpe@gmx.de + +- Fixed license to LGPL-3.0+ (SPDX style) + +------------------------------------------------------------------- +Wed Aug 24 14:17:26 UTC 2011 - mrueckert@suse.de + +- make sure the compiler commandlines are shown (V=1) +- make it build on sle11 again. we dont have pkg-config provides + there + +------------------------------------------------------------------- +Fri Aug 19 12:28:04 UTC 2011 - saschpe@suse.de + +- Use %makeinstall marcro instead of %make_install to fix build + on Mandriva and Fedora + +------------------------------------------------------------------- +Fri Aug 19 12:07:40 UTC 2011 - saschpe@suse.de + +- Add libuuid-devel to RedHat BuildRequires to fix build + +------------------------------------------------------------------- +Fri Aug 19 10:50:02 UTC 2011 - saschpe@suse.de + +- Update to version 2.1.7: + * Fixed issue 188, assert when closing socket that had unread multipart + data still on it (affected PULL, SUB, ROUTER, and DEALER sockets). + * Fixed issue 191, message atomicity issue with PUB sockets (an old issue). + * Fixed issue 199 (affected ROUTER/XREP sockets, an old issue). + * Fixed issue 206, assertion failure in zmq.cpp:223, affected all sockets + (bug was introduced in 2.1.6 as part of message validity checking). + * Fixed issue 211, REP socket asserted if sent malformed envelope (old issue + due to abuse of assertions for error checking). + * Fixed issue 212, reconnect failing after resume from sleep on Windows + (due to not handling WSAENETDOWN). + * Properly handle WSAENETUNREACH on Windows (e.g. if client connects + before server binds). + * Fixed memory leak with threads on Windows. +- Changes from previous releases: + * See https://raw.github.com/zeromq/zeromq2-1/master/NEWS +- Run spec-cleaner, added proper spec license header, shorter file lists +- Split out documentation package + +------------------------------------------------------------------- +Wed Dec 1 15:24:02 UTC 2010 - mrueckert@suse.de + +- update to version 2.0.10 + * Upgrade OpenPGM to 2.1.28~dfsg (Martin Lucina) + * Added a ZMQ_VERSION macro to zmq.h for compile-time API version + detection (Martin Sustrik, Gonzalo Diethelm, Martin Lucina) + * Fix memory leak under Windows (Taras Shpot) + * Makefile.am: Add missing files to distribution, improve + maintainer-clean (Martin Lucina) + * Add support for RHEL6 in the spec file (Sebastian Otaegui) + * configure.in: Do not patch libtool rpath handling (Martin Lucina) + * Fixing the Red Hat packaging (Martin Sustrik) + * zmq_msg_move called on uninitialised message in xrep_t::xrecv + -- fixed (Max Wolf) + * crash when closing an ypipe -- fixed (Dhammika Pathirana) + * REQ socket can die when reply is delivered on wrong unerlying + connection -- fixed (Martin Sustrik) + * if TSC jumps backwards (in case of migration to a + different CPU core) latency peak may occur -- fixed + (Martin Sustrik) + * values of RATE, RECOVERY_IVL and SWAP options are checked for + negative values (Martin Sustrik) +- added provides for libzmq-devel + +------------------------------------------------------------------- +Mon Sep 6 15:31:23 UTC 2010 - mrueckert@suse.de + +- initial package + diff --git a/saltbundle-zeromq.spec b/saltbundle-zeromq.spec new file mode 100644 index 0000000..f333e89 --- /dev/null +++ b/saltbundle-zeromq.spec @@ -0,0 +1,151 @@ +# +# spec file for package saltbundle-zeromq +# +# Copyright (c) 2021 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%global __brp_check_rpaths %{nil} + +%define lib_name saltbundle-libzmq + +Name: saltbundle-zeromq +Version: 4.2.3 +Release: 0 +Summary: Lightweight messaging kernel +License: LGPL-3.0-or-later +Group: Productivity/Networking/Web/Servers +URL: http://www.zeromq.org/ +Source: https://github.com/zeromq/libzmq/releases/download/v%{version}/zeromq-%{version}.tar.gz +Source1000: saltbundle-zeromq-rpmlintrc +Patch1: CVE-2019-6250.patch +Patch2: CVE-2019-13132.patch +Patch3: CVE-2020-15166.patch +Patch4: bsc1176259.patch +Patch5: bsc1176258.patch +Patch6: bsc1176256.patch +Patch7: bsc1176257.patch +%if 0%{?suse_version} == 1110 +BuildRequires: gcc48-c++ +%else +BuildRequires: gcc-c++ +%endif +BuildRequires: pkgconfig +BuildRequires: saltbundle-libsodium-devel +BuildRequires: pkgconfig(uuid) +AutoReqProv: 0 + +%description +The ZeroMQ messaging kernel is a library extending the standard +socket interfaces with an abstraction of asynchronous message queues, +multiple messaging patterns, message filtering (subscriptions) and +seamless access to multiple transport protocols. + +%package -n %{lib_name} +Summary: Shared Library for ZeroMQ +Group: Productivity/Networking/Web/Servers +Requires: saltbundle-libsodium +AutoReqProv: 0 + +%description -n %{lib_name} +The ZeroMQ messaging kernel is a library extending the standard +socket interfaces with an abstraction of asynchronous message queues, +multiple messaging patterns, message filtering (subscriptions) and +seamless access to multiple transport protocols. + +This package holds the shared library part of the ZeroMQ package. + +%package tools +Summary: Tools to work with ZeroMQ +# Conflict old libraries as we collide with them +Group: Productivity/Networking/Web/Servers +Conflicts: libzmq1 +Conflicts: libzmq2 +Conflicts: libzmq3 +AutoReqProv: 0 + +%description tools +The ZeroMQ messaging kernel is a library extending the standard +socket interfaces with an abstraction of asynchronous message queues, +multiple messaging patterns, message filtering (subscriptions) and +seamless access to multiple transport protocols. + +This package contains the utilities to work with ZeroMQ library. + +%package devel +Summary: Development files for ZeroMQ +Group: Development/Languages/C and C++ +Requires: %{lib_name} = %{version} +AutoReqProv: 0 + +%description devel +The ZeroMQ messaging kernel is a library extending the standard +socket interfaces with an abstraction of asynchronous message queues, +multiple messaging patterns, message filtering (subscriptions) and +seamless access to multiple transport protocols. + +This package holds the development files for ZeroMQ. + +%prep +%autosetup -p1 -n zeromq-%{version} + +%build +%ifarch i386 +export LIBS="-ldl -latomic" +%else +export LIBS=-ldl +%endif +%if 0%{?suse_version} == 1110 +export CXX=g++-4.8 +%endif +%configure \ + --with-libsodium \ + --enable-curve \ + --disable-static \ + --disable-dependency-tracking \ + --disable-silent-rules \ + --disable-Werror +make %{?_smp_mflags} + +%install +%make_install +find %{buildroot} -type f -name "*.la" -delete -print + +%check +%if ! 0%{?qemu_user_space_build} +# Tests don't run well concurrently and some are flaky, hence 3x before fail +make check %{?_smp_mflags} || make check || make check || make check || (cat ./test-suite.log && false) +%endif + +%post -n %{lib_name} -p /sbin/ldconfig +%postun -n %{lib_name} -p /sbin/ldconfig + +%files -n %{lib_name} +%license COPYING COPYING.LESSER +%{_libdir}/libzmq.so.* + +%files tools +%license COPYING COPYING.LESSER +%{_bindir}/curve_keygen + +%files devel +%doc AUTHORS ChangeLog NEWS +%license COPYING COPYING.LESSER +%{_includedir}/zmq* +%{_libdir}/libzmq.so +%{_libdir}/pkgconfig/libzmq.pc +%{_mandir}/man3/zmq*.3%{?ext_man} +%{_mandir}/man7/zmq*.7%{?ext_man} + +%changelog diff --git a/zeromq-4.2.3.tar.gz b/zeromq-4.2.3.tar.gz new file mode 100644 index 0000000..7e6e71a --- /dev/null +++ b/zeromq-4.2.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f1e2b2aade4dbfde98d82366d61baef2f62e812530160d2e6d0a5bb24e40bc0 +size 1326780