public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Michael Jeanson <mjeanson@efficios.com>
To: git-commits@fedoraproject.org
Subject: [rpms/babeltrace] rawhide: Add patches for CTF-2 and SWIG >= 4.3
Date: Thu, 04 Jun 2026 19:12:21 GMT	[thread overview]
Message-ID: <178060034157.1.17523441712958732597.rpms-babeltrace-5eeee0f9f9c3@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/babeltrace
Branch : rawhide
Commit : 5eeee0f9f9c3952a077854a205897885aeba36cf
Author : Michael Jeanson <mjeanson@efficios.com>
Date   : 2026-06-04T15:03:25-04:00
Stats  : +393/-1 in 3 file(s)
URL    : https://src.fedoraproject.org/rpms/babeltrace/c/5eeee0f9f9c3952a077854a205897885aeba36cf?branch=rawhide

Log:
Add patches for CTF-2 and SWIG >= 4.3

---
diff --git a/0001-Fix-handle-NULL-list-pointer-to-avoid-Python-segfaul.patch b/0001-Fix-handle-NULL-list-pointer-to-avoid-Python-segfaul.patch
new file mode 100644
index 0000000..b8ba580
--- /dev/null
+++ b/0001-Fix-handle-NULL-list-pointer-to-avoid-Python-segfaul.patch
@@ -0,0 +1,255 @@
+From d31f7484b80032b13cb70d743b0600c843e0fd89 Mon Sep 17 00:00:00 2001
+From: Christophe Bedard <bedard.christophe@gmail.com>
+Date: Wed, 29 Apr 2026 18:26:45 -0700
+Subject: [PATCH 1/2] Fix: handle NULL list pointer to avoid Python segfault
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Before a change in SWIG 4.3.0 [0], `AppendOutput(Py_None, count_obj)`
+returned just `count_obj`, an `int`, when an error happens. That value
+is garbage because `*len` (`== count_obj`) is not initialized by
+`bt_ctf_get_field_list()` & friends when they return an error (e.g.,
+when called for an event scope that does not exist on the event, like
+`EVENT_CONTEXT` on an event without per-event context). However, it's
+not a `list`, so `if not isinstance(ret, list): return` in
+`EventDeclaration.fields_scope()` (and other location) prevents it from
+resulting in a crash.
+
+After that change, SWIG returns `[None, count_obj]` (still with garbage
+`count_obj`) in this case since it's a non-void return (see the SWIG
+commit). This is unfortunately a `list`, so it keeps going, iterates
+`range(garbage_count)` and dereferences a `NULL` list pointer.
+
+```
+Current thread 0x000073d613434200 [python3] (most recent call first):
+  File "/usr/lib/python3/dist-packages/babeltrace/babeltrace.py", line 83 in _bt_python_field_one_from_list
+  File "/usr/lib/python3/dist-packages/babeltrace/babeltrace.py", line 839 in _field_list_with_scope
+  File "/usr/lib/python3/dist-packages/babeltrace/babeltrace.py", line 719 in field_list_with_scope
+  File "/usr/lib/python3/dist-packages/babeltrace/babeltrace.py", line 792 in keys
+```
+
+See the new Python regression test.
+
+Fix this on the Python caller side: `count` shouldn't be used if the
+call failed in the first place. If `[list_ptr, count]` is returned
+(always the case in SWIG >=4.3.0), make sure `list_ptr is not None`
+before interpreting `count`. The existing checks for
+`isinstance(ret, list)` handle SWIG <4.3.0 returning just `count` when
+the underlying call fails.
+
+I used Claude Opus 4.7 to identify and fix this issue. I've verified
+that this actually resolves the issue.
+
+[0] https://github.com/swig/swig/commit/cd39cf132c96a0887be07c826b80804d7677a701
+
+Fixes: #1439
+
+Change-Id: Ic9ab84c011337f89281879c280f1ed2fe6dbf11a
+Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
+Co-authored-by: Simon Marchi <simon.marchi@efficios.com>
+Reviewed-on: https://review.lttng.org/c/babeltrace/+/17654
+Reviewed-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+---
+ bindings/python/babeltrace/babeltrace.i.in    |  15 ++-
+ tests/Makefile.am                             |   3 +-
+ tests/bin/intersection/Makefile.am            |   9 +-
+ .../test_python_event_no_context.py           | 104 ++++++++++++++++++
+ 4 files changed, 123 insertions(+), 8 deletions(-)
+ create mode 100755 tests/bin/intersection/test_python_event_no_context.py
+
+diff --git a/bindings/python/babeltrace/babeltrace.i.in b/bindings/python/babeltrace/babeltrace.i.in
+index 8eec1c1d1..38f09068a 100644
+--- a/bindings/python/babeltrace/babeltrace.i.in
++++ b/bindings/python/babeltrace/babeltrace.i.in
+@@ -492,6 +492,8 @@ class TraceHandle(object):
+ 			return
+ 
+ 		ptr_list, count = ret
++		if ptr_list is None:
++			return
+ 		for i in range(count):
+ 			tmp = EventDeclaration.__new__(EventDeclaration)
+ 			tmp._ed =  _bt_python_decl_one_from_list(ptr_list, i)
+@@ -785,7 +787,7 @@ class Event(collections_abc.Mapping):
+ 		for scope in _scopes:
+ 			scope_ptr = _bt_ctf_get_top_level_scope(self._e, scope)
+ 			ret = _bt_python_field_listcaller(self._e, scope_ptr)
+-			if isinstance(ret, list):
++			if isinstance(ret, list) and ret[0] is not None:
+ 				count += ret[1]
+ 		return count
+ 
+@@ -834,12 +836,15 @@ class Event(collections_abc.Mapping):
+ 		fields = []
+ 		scope_ptr = _bt_ctf_get_top_level_scope(self._e, scope)
+ 
+-		# Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
+-		# provide the "count" return value
++		# SWIG returns [list_ptr, count] when the C call wrote a list, or
++		# just the count integer when it returned NULL (SWIG <= 4.2 only;
++		# SWIG >= 4.3 returns [None, garbage]). Treat both NULL forms as
++		# "no fields" since the count is unreliable when list_ptr is NULL
++		# because the C wrapper does not initialize it on error.
+ 		count = 0
+ 		list_ptr = None
+ 		ret = _bt_python_field_listcaller(self._e, scope_ptr)
+-		if isinstance(ret, list):
++		if isinstance(ret, list) and ret[0] is not None:
+ 			list_ptr, count = ret
+ 
+ 		for i in range(count):
+@@ -893,6 +898,8 @@ class EventDeclaration(object):
+ 			return
+ 
+ 		list_ptr, count = ret
++		if list_ptr is None:
++			return
+ 		for i in range(count):
+ 			field_declaration_ptr = _bt_python_field_decl_one_from_list(list_ptr, i)
+ 			if field_declaration_ptr is not None:
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 98c7473c0..d3d7e94f0 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -23,5 +23,6 @@ TESTS += lib/test_dwarf_complete \
+ endif
+ 
+ if USE_PYTHON
+-TESTS += bin/intersection/test_multi_trace_intersection.py
++TESTS += bin/intersection/test_multi_trace_intersection.py \
++	bin/intersection/test_python_event_no_context.py
+ endif
+diff --git a/tests/bin/intersection/Makefile.am b/tests/bin/intersection/Makefile.am
+index 6c7330e58..6f37220d5 100644
+--- a/tests/bin/intersection/Makefile.am
++++ b/tests/bin/intersection/Makefile.am
+@@ -1,9 +1,12 @@
+ check_SCRIPTS = test_intersection \
+ 		bt_python_helper.py \
+-		test_multi_trace_intersection.py
++		test_multi_trace_intersection.py \
++		test_python_event_no_context.py
+ 
+-dist_noinst_SCRIPTS = test_multi_trace_intersection.py
+-EXTRA_DIST=test_multi_trace_intersection.py
++dist_noinst_SCRIPTS = test_multi_trace_intersection.py \
++		test_python_event_no_context.py
++EXTRA_DIST = test_multi_trace_intersection.py \
++		test_python_event_no_context.py
+ 
+ all-local:
+ 	@if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+diff --git a/tests/bin/intersection/test_python_event_no_context.py b/tests/bin/intersection/test_python_event_no_context.py
+new file mode 100755
+index 000000000..d72534e89
+--- /dev/null
++++ b/tests/bin/intersection/test_python_event_no_context.py
+@@ -0,0 +1,104 @@
++#!/usr/bin/env python3
++#
++# The MIT License (MIT)
++#
++# Copyright (C) 2026 - EfficiOS, Inc.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++#
++# The above copyright notice and this permission notice shall be included in
++# all copies or substantial portions of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++# SOFTWARE.
++#
++# This test reproduces a crash that happened when keys() iterated the
++# EVENT_CONTEXT scope of an event with no per-event context.
++
++import bt_python_helper
++import tempfile
++import babeltrace
++import uuid
++import shutil
++
++
++def create_trace(path):
++    writer = babeltrace.CTFWriter.Writer(path)
++    clock = babeltrace.CTFWriter.Clock('test_clock')
++    clock.uuid = uuid.uuid4()
++    writer.add_clock(clock)
++
++    int_type = babeltrace.CTFWriter.IntegerFieldDeclaration(32)
++    event_class = babeltrace.CTFWriter.EventClass('simple_event')
++    event_class.add_field(int_type, 'int_field')
++
++    stream_class = babeltrace.CTFWriter.StreamClass('test_stream')
++    stream_class.add_event_class(event_class)
++    stream_class.clock = clock
++
++    stream = writer.create_stream(stream_class)
++
++    for i in range(5):
++        clock.time = i
++        event = babeltrace.CTFWriter.Event(event_class)
++        event.payload('int_field').value = i
++        stream.append_event(event)
++
++    stream.flush()
++
++
++def print_test_result(test_number, result, description):
++    result_string = 'ok' if result else 'not ok'
++    result_string += ' {} - {}'.format(test_number, description)
++    print(result_string)
++
++
++TEST_COUNT = 3
++
++print('1..{}'.format(TEST_COUNT))
++
++trace_path = tempfile.mkdtemp()
++print('# Creating trace at {}'.format(trace_path))
++create_trace(trace_path)
++
++traces = babeltrace.TraceCollection()
++trace_handle = traces.add_trace(trace_path, 'ctf')
++print_test_result(1, trace_handle is not None, 'Opening generated trace')
++
++context_fields_ok = True
++event_keys_ok = True
++event_count = 0
++
++if trace_handle is not None:
++    for event in traces.events:
++        event_count += 1
++
++        # The crash happened right here.
++        context_fields = event.field_list_with_scope(
++            babeltrace.CTFScope.EVENT_CONTEXT)
++        if context_fields != []:
++            print('# Unexpected event context fields: {}'.format(
++                context_fields))
++            context_fields_ok = False
++
++        keys = event.keys()
++        if 'int_field' not in keys:
++            print('# Unexpected event keys: {}'.format(keys))
++            event_keys_ok = False
++
++print_test_result(2, context_fields_ok,
++                  'Missing EVENT_CONTEXT returns an empty field list')
++print_test_result(3, event_keys_ok and event_count == 5,
++                  'keys() includes payload fields without crashing')
++
++shutil.rmtree(trace_path)
+-- 
+2.54.0
+

diff --git a/0002-Print-a-clear-error-when-reading-a-CTF-2-trace.patch b/0002-Print-a-clear-error-when-reading-a-CTF-2-trace.patch
new file mode 100644
index 0000000..d766718
--- /dev/null
+++ b/0002-Print-a-clear-error-when-reading-a-CTF-2-trace.patch
@@ -0,0 +1,131 @@
+From cc7676cd8312c71a645f8cd991a4e62cdffc2e4a Mon Sep 17 00:00:00 2001
+From: Philippe Proulx <eeppeliteloop@gmail.com>
+Date: Thu, 4 Jun 2026 09:41:55 -0400
+Subject: [PATCH 2/2] Print a clear error when reading a CTF 2 trace
+
+A CTF 2 metadata stream starts with an ASCII RS (0x1e) byte, which
+Babeltrace 1.x can't parse as TSDL.
+
+Detect it and fail with a message pointing to Babeltrace 2.1+ instead of
+confusing syntax errors.
+
+Resolves: S-2582
+Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
+Change-Id: If191d87c2b65a9df10c045c52d6ec2d01aea187d
+Reviewed-on: https://review.lttng.org/c/babeltrace/+/18016
+---
+ formats/ctf/ctf.c                       |  16 ++++++
+ tests/ctf-traces/fail/ctf-2/dummystream | Bin 0 -> 69 bytes
+ tests/ctf-traces/fail/ctf-2/metadata    |  72 ++++++++++++++++++++++++
+ 3 files changed, 88 insertions(+)
+ create mode 100644 tests/ctf-traces/fail/ctf-2/dummystream
+ create mode 100644 tests/ctf-traces/fail/ctf-2/metadata
+
+diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c
+index 1ba9017fd..96a1e066b 100644
+--- a/formats/ctf/ctf.c
++++ b/formats/ctf/ctf.c
+@@ -1503,6 +1503,22 @@ int ctf_trace_metadata_read(struct ctf_trace *td, FILE *metadata_fp,
+ 	if (babeltrace_debug)
+ 		yydebug = 1;
+ 
++	/* CTF 2 support starts with Babeltrace 2.1 */
++	{
++		const int first = fgetc(fp);
++
++		rewind(fp);
++
++		if (first == 0x1e) {
++			fprintf(stderr,
++				"[warning] This is a CTF 2 trace: you need Babeltrace 2.1+ to read it.\n"
++				"          Babeltrace 1.x has reached end of life and is no longer\n"
++				"          maintained: please upgrade.\n");
++			ret = -1;
++			goto end;
++		}
++	}
++
+ 	if (packet_metadata(td, fp)) {
+ 		ret = ctf_trace_metadata_stream_read(td, &fp, &buf);
+ 		if (ret) {
+diff --git a/tests/ctf-traces/fail/ctf-2/metadata b/tests/ctf-traces/fail/ctf-2/metadata
+new file mode 100644
+index 000000000..6ba75e858
+--- /dev/null
++++ b/tests/ctf-traces/fail/ctf-2/metadata
+@@ -0,0 +1,72 @@
++\x1e{
++  "type": "preamble",
++  "uuid": [
++    42,
++    100,
++    34,
++    208,
++    108,
++    238,
++    17,
++    224,
++    140,
++    8,
++    203,
++    7,
++    215,
++    179,
++    165,
++    100
++  ],
++  "version": 2
++}
++\x1e{
++  "packet-header-field-class": {
++    "member-classes": [
++      {
++        "field-class": {
++          "alignment": 32,
++          "byte-order": "little-endian",
++          "length": 32,
++          "preferred-display-base": 16,
++          "roles": [
++            "packet-magic-number"
++          ],
++          "type": "fixed-length-unsigned-integer"
++        },
++        "name": "magic"
++      },
++      {
++        "field-class": {
++          "length": 16,
++          "roles": [
++            "metadata-stream-uuid"
++          ],
++          "type": "static-length-blob"
++        },
++        "name": "uuid"
++      }
++    ],
++    "type": "structure"
++  },
++  "type": "trace-class",
++  "uid": "2a6422d0-6cee-11e0-8c08-cb07d7b3a564"
++}
++\x1e{
++  "type": "data-stream-class"
++}
++\x1e{
++  "name": "string",
++  "payload-field-class": {
++    "member-classes": [
++      {
++        "field-class": {
++          "type": "null-terminated-string"
++        },
++        "name": "str"
++      }
++    ],
++    "type": "structure"
++  },
++  "type": "event-record-class"
++}
+-- 
+2.54.0
+

diff --git a/babeltrace.spec b/babeltrace.spec
index f771269..ae88ddb 100644
--- a/babeltrace.spec
+++ b/babeltrace.spec
@@ -1,6 +1,6 @@
 Name:           babeltrace
 Version:        1.5.11
-Release:        18%{?dist}
+Release:        19%{?dist}
 Summary:        Trace Viewer and Converter, mainly for the Common Trace Format
 License:        MIT AND GPL-3.0-or-later WITH Bison-exception-2.2 AND LGPL-2.1-only AND BSD-4-Clause-UC
 URL:            https://www.efficios.com/babeltrace
@@ -9,6 +9,8 @@ Source1:        https://www.efficios.com/files/%{name}/%{name}-%{version}.tar.bz
 # gpg2 --export --export-options export-minimal 7F49314A26E0DE78427680E05F1B2A0789F12B11 > gpgkey-7F49314A26E0DE78427680E05F1B2A0789F12B11.gpg
 Source2:        gpgkey-7F49314A26E0DE78427680E05F1B2A0789F12B11.gpg
 Patch0:         babeltrace-getaddrinfo.patch
+Patch1:         0001-Fix-handle-NULL-list-pointer-to-avoid-Python-segfaul.patch
+Patch2:         0002-Print-a-clear-error-when-reading-a-CTF-2-trace.patch
 
 BuildRequires:  bison >= 2.4
 BuildRequires:  flex >= 2.5.35
@@ -117,6 +119,10 @@ rm -f %{buildroot}/%{_pkgdocdir}/std-ext-lib.txt
 
 
 %changelog
+* Thu Jun 04 2026 Michael Jeanson <mjeanson@efficios.com> - 1.5.11-19
+- Add patch to fix python segfault with swig >= 4.3
+- Add patch to print a clear error with CTF-2 traces
+
 * Wed Jun 03 2026 Python Maint <python-maint@redhat.com> - 1.5.11-18
 - Rebuilt for Python 3.15
 

                 reply	other threads:[~2026-06-04 19:12 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178060034157.1.17523441712958732597.rpms-babeltrace-5eeee0f9f9c3@fedoraproject.org \
    --to=mjeanson@efficios.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox