Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sofia-sip for openSUSE:Factory checked in at 2026-08-21 22:17:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sofia-sip (Old) and /work/SRC/openSUSE:Factory/.sofia-sip.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sofia-sip" Fri Aug 21 22:17:33 2026 rev:24 rq:1372905 version:1.13.18 Changes: -------- --- /work/SRC/openSUSE:Factory/sofia-sip/sofia-sip.changes 2026-06-05 14:58:34.800038025 +0200 +++ /work/SRC/openSUSE:Factory/.sofia-sip.new.1258/sofia-sip.changes 2026-08-21 22:17:39.854675353 +0200 @@ -1,0 +2,10 @@ +Thu Aug 20 11:58:43 UTC 2026 - Dominique Leuenberger <[email protected]> + +- Update to version 1.13.18: + + Make HEP capture buffer size configurable via `bufsize=` + + Clamp HEP capture payload to the buffer instead of dropping chunks + + Capture HEP messages after parsing instead of per recv + + [GHA] Skip mirror and meta jobs on public forks + + [GHA] Skip artifacts upload on public forks + +------------------------------------------------------------------- Old: ---- sofia-sip-1.13.17+50.tar.xz New: ---- sofia-sip-1.13.18.tar.xz sofia-sip.obsinfo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sofia-sip.spec ++++++ --- /var/tmp/diff_new_pack.AV0Y6d/_old 2026-08-21 22:17:40.625702890 +0200 +++ /var/tmp/diff_new_pack.AV0Y6d/_new 2026-08-21 22:17:40.627702962 +0200 @@ -19,7 +19,7 @@ %define pkg_major 1.13 %define with_doxygen 0 Name: sofia-sip -Version: 1.13.17+50 +Version: 1.13.18 Release: 0 Summary: A RFC3261 compliant SIP User-Agent library License: LGPL-2.1-or-later ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.AV0Y6d/_old 2026-08-21 22:17:40.658704069 +0200 +++ /var/tmp/diff_new_pack.AV0Y6d/_new 2026-08-21 22:17:40.662704212 +0200 @@ -1,6 +1,6 @@ -mtime: 1780297169 -commit: b677a9695cbbc7fe313ff1e166802d79932bed4cb96cf5081c4abaf71340f56b +mtime: 1787230743 +commit: c84652e2e757f6f83c7255258855d2b172f00ead0ed63d35d642f75c76a3bdfd url: https://src.opensuse.org/GNOME/sofia-sip -revision: b677a9695cbbc7fe313ff1e166802d79932bed4cb96cf5081c4abaf71340f56b +revision: c84652e2e757f6f83c7255258855d2b172f00ead0ed63d35d642f75c76a3bdfd projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj ++++++ _service ++++++ --- /var/tmp/diff_new_pack.AV0Y6d/_old 2026-08-21 22:17:40.682704926 +0200 +++ /var/tmp/diff_new_pack.AV0Y6d/_new 2026-08-21 22:17:40.685705033 +0200 @@ -3,9 +3,9 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://github.com/freeswitch/sofia-sip.git</param> - <param name="revision">54981e14d05e60b1ee547bd4c55647b85fe35e56</param> + <param name="revision">v1.13.18</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> - <param name="versionrewrite-pattern">v(.*)</param> + <param name="versionrewrite-pattern">v?(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> </service> <service name="tar" mode="manual"/> ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-08-20 14:59:03.000000000 +0200 @@ -0,0 +1,4 @@ +*.obscpio +*.osc +_build.* +.pbuild ++++++ sofia-sip-1.13.17+50.tar.xz -> sofia-sip-1.13.18.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/.github/workflows/build.yml new/sofia-sip-1.13.18/.github/workflows/build.yml --- old/sofia-sip-1.13.17+50/.github/workflows/build.yml 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/.github/workflows/build.yml 2026-08-03 23:14:22.000000000 +0200 @@ -52,6 +52,7 @@ TARGET_ARTIFACT_NAME: ${{ matrix.os }}-${{ matrix.version }}-${{ matrix.platform.name }}-public-unstable-artifact UPLOAD_BUILD_ARTIFACTS: >- ${{ + github.repository == 'freeswitch/sofia-sip' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish)) && (!github.event.pull_request || github.event.pull_request.head.repo.full_name == github.repository) }} @@ -66,6 +67,7 @@ name: 'DEB-MIRROR' if: >- ${{ + github.repository == 'freeswitch/sofia-sip' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish)) && (!github.event.pull_request || github.event.pull_request.head.repo.full_name == github.repository) }} @@ -133,8 +135,9 @@ name: 'Publish build data to meta-repo' if: >- ${{ - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && inputs.publish) + github.repository == 'freeswitch/sofia-sip' && + (github.event_name == 'push' || + (github.event_name == 'workflow_dispatch' && inputs.publish)) }} needs: - deb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/.update new/sofia-sip-1.13.18/.update --- old/sofia-sip-1.13.17+50/.update 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/.update 2026-08-03 23:14:22.000000000 +0200 @@ -1 +1 @@ -Tue Nov 07 13:51:10 UTC 2023 +Mon Aug 03 21:04:40 UTC 2026 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/configure.ac new/sofia-sip-1.13.18/configure.ac --- old/sofia-sip-1.13.17+50/configure.ac 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/configure.ac 2026-08-03 23:14:22.000000000 +0200 @@ -11,7 +11,7 @@ dnl --------------------------- dnl update both the version for AC_INIT and the LIBSOFIA_SIP_UA_MAJOR_MINOR -AC_INIT([sofia-sip], [1.13.17]) +AC_INIT([sofia-sip], [1.13.18]) CFLAGS="$CFLAGS $CONFIGURE_CFLAGS" CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/debian/changelog new/sofia-sip-1.13.18/debian/changelog --- old/sofia-sip-1.13.17+50/debian/changelog 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/debian/changelog 2026-08-03 23:14:22.000000000 +0200 @@ -1,3 +1,9 @@ +sofia-sip (1.13.18-0) unstable; urgency=medium + + * New Release. + + -- FreeSWITCH Solutions <[email protected]> Mon, 03 Aug 2026 23:04:40 +0200 + sofia-sip (1.13.17-0) unstable; urgency=medium * New Release. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/Makefile.am new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/Makefile.am --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/Makefile.am 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/Makefile.am 2026-08-03 23:14:22.000000000 +0200 @@ -28,6 +28,18 @@ TESTS += torture_sresolv run_test_sresolv +check_PROGRAMS += torture_sres_domain +TESTS += torture_sres_domain +# Includes sres.c to reach the static name decoder, so link the sibling +# objects directly instead of libsresolv.la (which carries its own sres.o). +torture_sres_domain_SOURCES = torture_sres_domain.c \ + sres_cache.c sres_blocking.c sresolv.c sres_sip.c +# Per-target flags give these shared sources unique object names +# (torture_sres_domain-*.o), so they do not clash with the libtool objects +# libsresolv.la builds from the same files. +torture_sres_domain_CPPFLAGS = $(AM_CPPFLAGS) +torture_sres_domain_LDADD = ../url/liburl.la ../bnf/libbnf.la ../su/libsu.la + CLEANFILES = resolv.conf error.conf named.conf.tmp \ .test_sresolv.api.conf.?????? \ named.run diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/sres.c new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/sres.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/sres.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/sres.c 2026-08-03 23:14:22.000000000 +0200 @@ -4335,6 +4335,10 @@ { uint8_t cnt; unsigned i = 0; + unsigned n_pointers = 0; + /* Each compression pointer is two bytes, so a valid name follows at most + half the message size in distinct pointers; more means a cycle. */ + unsigned max_pointers = m->m_size / 2; uint8_t *p = m->m_data; uint16_t new_offset; int save_offset; @@ -4362,7 +4366,10 @@ if (save_offset) m->m_offset = offset; - if (new_offset <= 0 || new_offset >= m->m_size) { + /* Reject out-of-range jumps, and cap the number of pointer follows so a + cyclic chain terminates (see max_pointers above). */ + if (new_offset <= 0 || new_offset >= m->m_size || + ++n_pointers > max_pointers) { m->m_error = "invalid domain compression"; return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/torture_sres_domain.c new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/torture_sres_domain.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/sresolv/torture_sres_domain.c 1970-01-01 01:00:00.000000000 +0100 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/sresolv/torture_sres_domain.c 2026-08-03 23:14:22.000000000 +0200 @@ -0,0 +1,141 @@ +/**@internal + * + * @CFILE torture_sres_domain.c Unit tests for DNS name decompression. + * + * Exercises the resolver's domain-name decoder (`m_get_domain()`) directly + * with hand-built messages. The core file is included so the otherwise static + * decoder can be called without going through the network receive path. + */ + +#include "config.h" + +#include "sres.c" + +#include <sofia-sip/su_log.h> + +#if HAVE_ALARM +#include <signal.h> +#endif + +#define TSTFLAGS tstflags +int tstflags; + +#include <sofia-sip/tstdef.h> + +char const name[] = "torture_sres_domain"; + +extern su_log_t sresolv_log[]; + +/* Encode a 16-bit compression pointer to the given offset (two bytes). */ +static void put_pointer(uint8_t *p, unsigned at, unsigned target) +{ + p[at] = (uint8_t)(0xc0 | ((target >> 8) & 0x3f)); + p[at + 1] = (uint8_t)(target & 0xff); +} + +/* A name whose compression pointers form a cycle must be rejected and the + decode must terminate rather than loop. */ +static int test_pointer_cycle(void) +{ + sres_message_t m[1]; + char buf[1026]; + unsigned len; + + BEGIN(); + + /* Two pointers referencing each other: offset 12 -> 14 -> 12. */ + memset(m, 0, sizeof m); + put_pointer(m->m_data, 12, 14); + put_pointer(m->m_data, 14, 12); + m->m_size = 64; + len = m_get_domain(buf, sizeof buf, m, 12); + TEST(len, 0); + TEST_1(m->m_error != NULL); + TEST_S(m->m_error, "invalid domain compression"); + + /* A pointer that references its own offset: 12 -> 12. */ + memset(m, 0, sizeof m); + put_pointer(m->m_data, 12, 12); + m->m_size = 64; + len = m_get_domain(buf, sizeof buf, m, 12); + TEST(len, 0); + TEST_1(m->m_error != NULL); + TEST_S(m->m_error, "invalid domain compression"); + + END(); +} + +/* A name that uses a backward compression pointer decodes to the full name. */ +static int test_valid_compression(void) +{ + sres_message_t m[1]; + uint8_t *p; + unsigned o, name2, len; + char buf[1026]; + + BEGIN(); + + memset(m, 0, sizeof m); + p = m->m_data; + + /* Base name "sip.example.com" at offset 12. */ + o = 12; + p[o++] = 3; p[o++] = 's'; p[o++] = 'i'; p[o++] = 'p'; + p[o++] = 7; memcpy(p + o, "example", 7); o += 7; + p[o++] = 3; p[o++] = 'c'; p[o++] = 'o'; p[o++] = 'm'; + p[o++] = 0; + + /* Second name "www" followed by a pointer back to the base name. */ + name2 = o; + p[o++] = 3; p[o++] = 'w'; p[o++] = 'w'; p[o++] = 'w'; + put_pointer(p, o, 12); o += 2; + + m->m_size = 64; + + memset(buf, 0, sizeof buf); + len = m_get_domain(buf, sizeof buf, m, (uint16_t)name2); + TEST_1(m->m_error == NULL); + TEST_S(buf, "www.sip.example.com."); + TEST(len, 20); + + END(); +} + +#if HAVE_ALARM +static RETSIGTYPE sig_alarm(int s) +{ + fprintf(stderr, "%s: FAIL! test timeout!\n", name); + exit(1); +} +#endif + +int main(int argc, char **argv) +{ + int i; + int error = 0; + int o_alarm = 1; + + for (i = 1; argv[i]; i++) { + if (strcmp(argv[i], "-v") == 0) + tstflags |= tst_verbatim; + else if (strcmp(argv[i], "-a") == 0) + tstflags |= tst_abort; + else if (strcmp(argv[i], "--no-alarm") == 0) + o_alarm = 0; + } + +#if HAVE_ALARM + if (o_alarm) { + alarm(30); + signal(SIGALRM, sig_alarm); + } +#endif + + if (!(tstflags & tst_verbatim)) + su_log_soft_set_level(sresolv_log, 0); + + error |= test_pointer_cycle(); + error |= test_valid_compression(); + + return error; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport.c 2026-08-03 23:14:22.000000000 +0200 @@ -102,6 +102,11 @@ #define TP_STACK tp_master->mr_stack +/* Upper bound on how much of a received message is reassembled for HEP + * capture. Large or heavily fragmented messages may be captured truncated; + * raise this if that happens. */ +#define TPORT_CAPT_IOVMAX 80 + /* Define macros for rbtree implementation */ #define TP_LEFT(tp) ((tp)->tp_left) #define TP_RIGHT(tp) ((tp)->tp_right) @@ -2743,8 +2748,17 @@ { if (self) { tport_master_t *mr = self->tp_master; - msg_t *msg = mr->mr_tpac->tpac_alloc(mr->mr_stack, mr->mr_log, - NULL, size, self, NULL); + int flags = mr->mr_log; + msg_t *msg; + + /* Capture rebuilds the payload via msg_iovec(), which needs the + * header wire image that only MSG_DO_EXTRACT_COPY preserves. */ + if (mr->mr_capt_sock) { + flags |= MSG_DO_EXTRACT_COPY; + } + + msg = mr->mr_tpac->tpac_alloc(mr->mr_stack, flags, + NULL, size, self, NULL); if (msg) { su_addrinfo_t *mai = msg_addrinfo(msg); su_addrinfo_t const *tai = self->tp_addrinfo; @@ -3056,6 +3070,8 @@ if (self->tp_rlogged != msg) self->tp_rlogged = NULL; + if (self->tp_rcaptured != msg) + self->tp_rcaptured = NULL; self->tp_msg = msg; } @@ -3115,6 +3131,26 @@ self->tp_rlogged = msg; } + /* Capture needs the wire image MSG_FLG_EXTRACT_COPY preserves; messages + * allocated before capture was enabled lack it, so skip them. */ + if (!error && self->tp_master->mr_capt_sock && msg != self->tp_rcaptured + && msg_get_flags(msg, MSG_FLG_EXTRACT_COPY)) { + msg_iovec_t iov[TPORT_CAPT_IOVMAX]; + size_t i, iovlen = msg_iovec(msg, iov, TPORT_CAPT_IOVMAX); + size_t bytes = 0; + + for (i = 0; i < iovlen && i < TPORT_CAPT_IOVMAX; i++) { + bytes += iov[i].mv_len; + } + + if (bytes > 0) { + tport_capt_msg(self, msg, bytes, iov, + iovlen < TPORT_CAPT_IOVMAX ? iovlen : TPORT_CAPT_IOVMAX, + "recv"); + } + self->tp_rcaptured = msg; + } + SU_DEBUG_7(("%s(%p): %smsg %p ("MOD_ZU" bytes)" " from " TPN_FORMAT " next=%p\n", __func__, (void *)self, error ? "bad " : "", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_internal.h new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_internal.h --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_internal.h 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_internal.h 2026-08-03 23:14:22.000000000 +0200 @@ -212,6 +212,7 @@ msg_t *tp_msg; /**< Message being received */ msg_t const *tp_rlogged; /**< Last logged when receiving */ + msg_t const *tp_rcaptured; /**< Last HEP-captured when receiving */ su_time_t tp_rtime; /**< Last time received data */ unsigned short tp_ping; /**< Whitespace ping being received */ @@ -310,6 +311,7 @@ tport_primary_t *mr_primaries; /**< List of primary contacts */ unsigned mr_prot_ver; /* hep version */ unsigned mr_agent_id; /* agent version */ + unsigned mr_capt_bufsize; /* per-message HEP capture buffer cap (bytes). */ tport_params_t mr_params[1]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_logging.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_logging.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_logging.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_logging.c 2026-08-03 23:14:22.000000000 +0200 @@ -47,6 +47,10 @@ #define TPORT_STAMP_SIZE 144 +/** Default per-message HEP capture buffer cap in bytes, + * used when no bufsize= parameter is given in TPORT_CAPT. */ +#define TPORT_CAPT_BUFSIZE_DEFAULT 16000 + /**@var TPORT_LOG * * Environment variable determining if parsed message contents are logged. @@ -201,13 +205,14 @@ snprintf(port, sizeof(port), "%d", iport); - /* default values for capture protocol and agent id */ + /* default values for capture protocol, agent id, and per-message buffer cap */ mr->mr_prot_ver = 3; - mr->mr_agent_id = 200; - - /* get all params */ - while(p) - { + mr->mr_agent_id = 200; + mr->mr_capt_bufsize = TPORT_CAPT_BUFSIZE_DEFAULT; + + /* get all params */ + while(p) + { /* check ; in the URL */ if( (p = strchr(p+1, ';')) == 0 ) { break; @@ -238,8 +243,20 @@ return n; } } + else if(strncmp(p, "bufsize=", 8) == 0) { + unsigned bs; + + p += 8; + bs = (unsigned)atoi(p); + /* HEP envelope length is u16; cap accordingly with headroom for chunks */ + if (bs < 2048 || bs > 65000) { + su_log("invalid bufsize; must be in [2048, 65000]\n"); + return n; + } + mr->mr_capt_bufsize = bs; + } else { - su_log("unsupported capture param\n"); + su_log("unsupported capture param\n"); return n; } } @@ -480,8 +497,8 @@ #endif #if SU_HAVE_IN6 struct hep_ip6hdr hep_ip6header = {{{{0}}}}; -#endif - int eth_frame_len = 16000; +#endif + unsigned capt_bufsize; size_t i, dst = 1; tport_master_t *mr; @@ -491,6 +508,7 @@ su_self = self->tp_pri->pri_primary->tp_addr; mr = self->tp_master; + capt_bufsize = mr->mr_capt_bufsize; if (mr->mr_capt_src_addr) { /* override SRC address with configuration */ su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr; @@ -506,7 +524,7 @@ } /*buffer for ethernet frame*/ - *buffer = (void*)malloc(eth_frame_len); + *buffer = (void*)malloc(capt_bufsize); /* VOIP Header */ hep_header.hp_v = mr->mr_prot_ver; @@ -548,7 +566,7 @@ } /* Copy hepheader */ - memset(*buffer, '\0', eth_frame_len); + memset(*buffer, '\0', capt_bufsize); memcpy(*buffer, &hep_header, sizeof(struct hep_hdr)); buflen = sizeof(struct hep_hdr); @@ -584,17 +602,19 @@ buflen += sizeof(struct hep_timehdr); } - for (i = 0; i < iovused && n > 0; i++) { + for (i = 0; i < iovused && n > 0 && buflen < capt_bufsize; i++) { size_t len = iov[i].mv_len; + size_t room = capt_bufsize - buflen; + if (len > n) - len = n; - /* if the packet too big for us */ - if((buflen + len) > eth_frame_len) - break; - - memcpy(*buffer + buflen , (void*)iov[i].mv_base, len); - buflen +=len; - n -= len; + len = n; + /* clamp to remaining capture buffer */ + if (len > room) + len = room; + + memcpy(*buffer + buflen, (void*)iov[i].mv_base, len); + buflen += len; + n -= len; } return buflen; @@ -620,13 +640,12 @@ su_time_t now; hep_chunk_ip4_t src_ip4 = {{0}}, dst_ip4 = {{0}}; hep_chunk_t payload_chunk; - int orig_n = 0; - + #if SU_HAVE_IN6 hep_chunk_ip6_t src_ip6 = {{0}}, dst_ip6 = {{0}}; #endif - int eth_frame_len = 16000; + unsigned capt_bufsize; size_t i, dst = 1; tport_master_t *mr; @@ -636,6 +655,7 @@ su_self = self->tp_pri->pri_primary->tp_addr; mr = self->tp_master; + capt_bufsize = mr->mr_capt_bufsize; if (mr->mr_capt_src_addr) { /* override SRC address with configuration */ su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr; @@ -766,16 +786,19 @@ /* Payload caclulation */ - orig_n = n; - for (i = 0; i < iovused && n > 0; i++) { - size_t len = iov[i].mv_len; - if (len > n) len = n; - if((payload_len + len) > eth_frame_len) break; - payload_len +=len; - n -= len; + for (i = 0; i < iovused && n > 0 && payload_len < capt_bufsize; i++) { + size_t len = iov[i].mv_len; + size_t room = capt_bufsize - payload_len; + + if (len > n) + len = n; + /* clamp to remaining capture buffer instead of dropping the chunk */ + if (len > room) + len = room; + + payload_len += len; + n -= len; } - /* restore n */ - n = orig_n; /* Payload */ payload_chunk.vendor_id = htons(0x0000); @@ -822,17 +845,17 @@ memcpy((char*) *buffer+buflen, &payload_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); - /* PAYLOAD */ - for (i = 0; i < iovused && n > 0; i++) { + /* PAYLOAD: copy the payload_len bytes counted above (keeps buflen == tlen). + * payload_len is already folded into tlen/header.length, so consume it. */ + for (i = 0; i < iovused && payload_len > 0; i++) { size_t len = iov[i].mv_len; - if (len > n) len = n; - /* if the packet too big for us */ - if((buflen + len) > eth_frame_len) - break; - - memcpy(*buffer + buflen , (void*)iov[i].mv_base, len); - buflen +=len; - n -= len; + + if (len > payload_len) + len = payload_len; + + memcpy(*buffer + buflen, (void*)iov[i].mv_base, len); + buflen += len; + payload_len -= len; } free(hg); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_sctp.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_sctp.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_sctp.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_sctp.c 2026-08-03 23:14:22.000000000 +0200 @@ -260,9 +260,6 @@ if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, N, iovec, veclen, "recv", "from"); - if (self->tp_master->mr_capt_sock) - tport_capt_msg(self, msg, N, iovec, veclen, "recv"); - msg_recv_commit(msg, N, 0); /* Mark buffer as used */ return 2; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_tcp.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_tcp.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_tcp.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_tcp.c 2026-08-03 23:14:22.000000000 +0200 @@ -353,10 +353,6 @@ /* Write the received data to the message dump file */ if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from"); - - if (self->tp_master->mr_capt_sock) - tport_capt_msg(self, msg, n, iovec, veclen, "recv"); - /* Mark buffer as used */ msg_recv_commit(msg, n, n == 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_tls.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_tls.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_tls.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_tls.c 2026-08-03 23:14:22.000000000 +0200 @@ -468,9 +468,6 @@ if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from"); - if (self->tp_master->mr_capt_sock) - tport_capt_msg(self, msg, n, iovec, veclen, "recv"); - /* Mark buffer as used */ msg_recv_commit(msg, N, 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_udp.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_udp.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_udp.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_udp.c 2026-08-03 23:14:22.000000000 +0200 @@ -362,9 +362,6 @@ if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from"); - - if (self->tp_master->mr_capt_sock) - tport_capt_msg(self, msg, n, iovec, veclen, "recv"); *sample = *((uint8_t *)iovec[0].mv_base); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_ws.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_ws.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/tport_type_ws.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/tport_type_ws.c 2026-08-03 23:14:22.000000000 +0200 @@ -242,22 +242,23 @@ msg_set_address(msg, self->tp_addr, self->tp_addrlen); for (i = 0, n = 0; i < veclen; i++) { - m = iovec[i].mv_len; assert(N >= n + m); + m = iovec[i].mv_len; + assert(N >= n + m); + memcpy(iovec[i].mv_base, data + n, m); n += m; } - assert(N == n); + assert(n <= N); /* Write the received data to the message dump file */ if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from"); - if (self->tp_master->mr_capt_sock) - tport_capt_msg(self, msg, n, iovec, veclen, "recv"); - - /* Mark buffer as used */ - msg_recv_commit(msg, N, 0); + /* Mark buffer as used. The provisioned buffer is shorter than the frame + * when the message exceeds its size limit: the parser gets a prefix, + * flags it, and the reply path answers 413. */ + msg_recv_commit(msg, n, 0); return 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/ws.c new/sofia-sip-1.13.18/libsofia-sip-ua/tport/ws.c --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/ws.c 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/ws.c 2026-08-03 23:14:22.000000000 +0200 @@ -29,8 +29,14 @@ #define WS_WRITE_SANITY 200 #define SHA1_HASH_SIZE 20 + +/* Caps a whole message, not one frame. A backstop on how much a peer can + * make this layer allocate; the message size policy belongs to the SIP + * layer, so keep this above NTA's 2 MiB sa_maxsize default. */ +#define WS_PAYLOAD_SIZE_MAX_DEFAULT (4 * 1024 * 1024) + static struct ws_globals_s ws_globals; -ssize_t ws_global_payload_size_max = 0; +ssize_t ws_global_payload_size_max = WS_PAYLOAD_SIZE_MAX_DEFAULT; #ifndef WSS_STANDALONE @@ -713,9 +719,14 @@ return 0; } +/* The cap is what bounds a peer-driven allocation, so it cannot be turned + * off: a non-positive limit falls back to the default. Applies to handles + * created after this call. A consumer that raises NTA's sa_maxsize above the + * cap has to raise the cap too, otherwise a message sized between the two is + * dropped here instead of reaching the SIP layer. */ void ws_set_global_payload_size_max(ssize_t bytes) { - ws_global_payload_size_max = bytes; + ws_global_payload_size_max = bytes > 0 ? bytes : WS_PAYLOAD_SIZE_MAX_DEFAULT; } int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int block, int stay_open) @@ -740,8 +751,9 @@ wsh->buflen = 1024 * 64; wsh->bbuflen = wsh->buflen; - wsh->buffer = malloc(wsh->buflen); - wsh->bbuffer = malloc(wsh->bbuflen); + /* +1 NUL slot — see wsh_t in ws.h. */ + wsh->buffer = malloc(wsh->buflen + 1); + wsh->bbuffer = malloc(wsh->bbuflen + 1); //printf("init %p %ld\n", (void *) wsh->bbuffer, wsh->bbuflen); //memset(wsh->buffer, 0, wsh->buflen); //memset(wsh->bbuffer, 0, wsh->bbuflen); @@ -910,7 +922,7 @@ char *maskp; int ll = 0; int frag = 0; - int blen; + ssize_t blen; wsh->body = wsh->bbuffer; wsh->packetlen = 0; @@ -993,7 +1005,7 @@ wsh->payload = &wsh->buffer[2]; if (wsh->plen == 127) { - uint64_t *u64; + uint64_t len; need += 8; @@ -1006,9 +1018,19 @@ } } - u64 = (uint64_t *) wsh->payload; + len = ntoh64(*(uint64_t *) wsh->payload); wsh->payload += 8; - wsh->plen = ntoh64(*u64); + + /* Bound it while still unsigned: the cap is an ssize_t, so + * passing this makes the assignment below exact even where + * ssize_t is 32 bits. Subsumes RFC 6455 5.2's top-bit rule. */ + if (len > (uint64_t)wsh->payload_size_max) { + /* size limit */ + *oc = WSOC_CLOSE; + return ws_close(wsh, WS_NONE); + } + + wsh->plen = (ssize_t)len; } else if (wsh->plen == 126) { uint16_t *u16; @@ -1033,6 +1055,16 @@ wsh->payload += 4; } + blen = wsh->body - wsh->bbuffer; + + /* Subtract rather than test blen + plen, the sum that must not + * overflow; bounding it here keeps the sizing below overflow-free. */ + if (wsh->plen > wsh->payload_size_max - blen) { + /* size limit */ + *oc = WSOC_CLOSE; + return ws_close(wsh, WS_NONE); + } + need = (wsh->plen - (wsh->datalen - need)); if (need < 0) { @@ -1041,20 +1073,15 @@ return ws_close(wsh, WS_NONE); } - blen = wsh->body - wsh->bbuffer; - - if (need + blen > (ssize_t)wsh->bbuflen) { + /* Body must hold blen accumulated bytes plus this frame's + * full payload; the cap check above bounds that sum. */ + if (blen + wsh->plen > (ssize_t)wsh->bbuflen) { void *tmp; - wsh->bbuflen = need + blen + wsh->rplen; - - if (wsh->payload_size_max && wsh->bbuflen > wsh->payload_size_max) { - /* size limit */ - *oc = WSOC_CLOSE; - return ws_close(wsh, WS_NONE); - } + wsh->bbuflen = blen + wsh->plen; - if ((tmp = realloc(wsh->bbuffer, wsh->bbuflen))) { + /* +1 NUL slot — see wsh_t in ws.h. */ + if ((tmp = realloc(wsh->bbuffer, wsh->bbuflen + 1))) { wsh->bbuffer = tmp; } else { abort(); @@ -1086,7 +1113,9 @@ if (mask && maskp) { ssize_t i; - for (i = 0; i < wsh->datalen; i++) { + /* Unmask payload only. wsh->datalen tracks bytes in wsh->buffer + * (header + frame), but wsh->body holds just the rplen payload bytes.*/ + for (i = 0; i < wsh->rplen; i++) { wsh->body[i] ^= maskp[i % 4]; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/ws.h new/sofia-sip-1.13.18/libsofia-sip-ua/tport/ws.h --- old/sofia-sip-1.13.17+50/libsofia-sip-ua/tport/ws.h 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/libsofia-sip-ua/tport/ws.h 2026-08-03 23:14:22.000000000 +0200 @@ -92,6 +92,9 @@ typedef struct wsh_s { ws_socket_t sock; + /* buffer/bbuffer are allocated as buflen+1 / bbuflen+1; the trailing + * byte is reserved as a NUL terminator slot. buflen/bbuflen track + * usable content length, not allocation size. */ char *buffer; char *bbuffer; char *body; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/open_c/config.h.in new/sofia-sip-1.13.18/open_c/config.h.in --- old/sofia-sip-1.13.17+50/open_c/config.h.in 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/open_c/config.h.in 2026-08-03 23:14:22.000000000 +0200 @@ -382,13 +382,13 @@ #define PACKAGE_NAME "sofia-sip" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "sofia-sip 1.13.17work" +#define PACKAGE_STRING "sofia-sip 1.13.18work" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "sofia-sip" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.13.17work" +#define PACKAGE_VERSION "1.13.18work" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void @@ -408,7 +408,7 @@ #define TIME_WITH_SYS_TIME 1 /* Version number of package */ -#define VERSION "1.13.17work" +#define VERSION "1.13.18work" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sofia-sip-1.13.17+50/sofia-sip.spec new/sofia-sip-1.13.18/sofia-sip.spec --- old/sofia-sip-1.13.17+50/sofia-sip.spec 2026-05-11 18:14:48.000000000 +0200 +++ new/sofia-sip-1.13.18/sofia-sip.spec 2026-08-03 23:14:22.000000000 +0200 @@ -1,5 +1,5 @@ Name: sofia-sip -Version: 1.13.17 +Version: 1.13.18 Release: 1%{?dist} Summary: Sofia SIP User-Agent library ++++++ sofia-sip.obsinfo ++++++ name: sofia-sip version: 1.13.18 mtime: 1785791662 commit: ad36ac8f755308e8b87f98a505e83d4e408e5cc3
