Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libxmlb for openSUSE:Factory checked in at 2026-08-01 18:27:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libxmlb (Old) and /work/SRC/openSUSE:Factory/.libxmlb.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libxmlb" Sat Aug 1 18:27:24 2026 rev:23 rq:1368367 version:0.3.29 Changes: -------- --- /work/SRC/openSUSE:Factory/libxmlb/libxmlb.changes 2026-05-24 19:34:14.683818215 +0200 +++ /work/SRC/openSUSE:Factory/.libxmlb.new.16738/libxmlb.changes 2026-08-01 18:27:47.296644785 +0200 @@ -1,0 +2,22 @@ +Tue Jul 28 08:15:35 UTC 2026 - Bjørn Lie <[email protected]> + +- Update to version 0.3.29: + + Bugfixes: + - Avoid stale query indexes when reloading the silo + - Clear the query cache when reloading the silo + - Correctly mark the silo as invalid when re-loading malformed + data + - Fix building the silo when shared-mime-info is installed +- Changes from version 0.3.28: + + New Features: + - Automatically add system locales when using native-langs + - Lower the Meson and GLib deps for RHEL-8 + + Bugfixes: + - Lazy clear opcode tokens for a ~2% speedup + - Speed up negative queries by 11% by defer creating the + results objects + - Speed up predicates with no bindings by 9% + - Speed up the no-results query by 2.5% by using a constant + error + +------------------------------------------------------------------- Old: ---- libxmlb-0.3.27.tar.gz New: ---- libxmlb-0.3.29.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libxmlb.spec ++++++ --- /var/tmp/diff_new_pack.sHm6jy/_old 2026-08-01 18:27:48.152673827 +0200 +++ /var/tmp/diff_new_pack.sHm6jy/_new 2026-08-01 18:27:48.160674098 +0200 @@ -19,7 +19,7 @@ %define sover 2 Name: libxmlb -Version: 0.3.27 +Version: 0.3.29 Release: 0 Summary: Library for querying compressed XML metadata License: LGPL-2.1-or-later ++++++ libxmlb-0.3.27.tar.gz -> libxmlb-0.3.29.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/.github/workflows/main.yml new/libxmlb-0.3.29/.github/workflows/main.yml --- old/libxmlb-0.3.27/.github/workflows/main.yml 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/.github/workflows/main.yml 2026-07-27 17:01:51.000000000 +0200 @@ -20,6 +20,6 @@ - debian fail-fast: false steps: - - uses: actions/[email protected] + - uses: actions/[email protected] - run: docker build -t libxmlb-${{ matrix.distro }} -f contrib/ci/Dockerfile-${{ matrix.distro }} . - run: docker run -t -v `pwd`:/build libxmlb-${{ matrix.distro }} ./contrib/ci/build-${{ matrix.distro }}.sh diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/.github/workflows/scorecard.yml new/libxmlb-0.3.29/.github/workflows/scorecard.yml --- old/libxmlb-0.3.27/.github/workflows/scorecard.yml 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/.github/workflows/scorecard.yml 2026-07-27 17:01:51.000000000 +0200 @@ -32,12 +32,12 @@ steps: - name: "Checkout code" - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.1.1 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4.1.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 with: results_file: results.sarif results_format: sarif @@ -68,6 +68,6 @@ # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v3.29.5 + uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v3.29.5 with: sarif_file: results.sarif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/NEWS new/libxmlb-0.3.29/NEWS --- old/libxmlb-0.3.27/NEWS 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/NEWS 2026-07-27 17:01:51.000000000 +0200 @@ -1,3 +1,28 @@ +Version 0.3.29 +~~~~~~~~~~~~~~ +Released: 2026-07-27 + +New Features: +Bugfixes: + - Avoid stale query indexes when reloading the silo (Richard Hughes) + - Clear the query cache when reloading the silo (Richard Hughes) + - Correctly mark the silo as invalid when re-loading malformed data (Richard Hughes) + - Fix building the silo when shared-mime-info is installed (Richard Hughes) + +Version 0.3.28 +~~~~~~~~~~~~~~ +Released: 2026-06-30 + +New Features: + - Automatically add system locales when using native-langs (Richard Hughes) + - Lower the Meson and GLib deps for RHEL-8 (Richard Hughes) + +Bugfixes: + - Lazy clear opcode tokens for a ~2% speedup (Richard Hughes) + - Speed up negative queries by 11% by defer creating the results objects (Richard Hughes) + - Speed up predicates with no bindings by 9% (Richard Hughes) + - Speed up the no-results query by 2.5% by using a constant error (Richard Hughes) + Version 0.3.27 ~~~~~~~~~~~~~~ Released: 2026-05-18 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/RELEASE new/libxmlb-0.3.29/RELEASE --- old/libxmlb-0.3.27/RELEASE 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/RELEASE 2026-07-27 17:01:51.000000000 +0200 @@ -2,9 +2,9 @@ 1. Write NEWS entries for libxmlb in the same format as usual. -git shortlog 0.3.26.. | grep -i -v trivial | grep -v Merge > NEWS.new +git shortlog 0.3.28.. | grep -i -v trivial | grep -v Merge > NEWS.new -Version 0.3.27 +Version 0.3.29 ~~~~~~~~~~~~~~ Released: 2026-xx-xx @@ -15,7 +15,7 @@ Commit changes to git: # MAKE SURE THESE ARE CORRECT -export release_ver="0.3.27" +export release_ver="0.3.29" git commit -a -m "Release libxmlb ${release_ver}" --no-verify git tag -s -f -m "Release libxmlb ${release_ver}" "${release_ver}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/SECURITY.md new/libxmlb-0.3.29/SECURITY.md --- old/libxmlb-0.3.27/SECURITY.md 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/SECURITY.md 2026-07-27 17:01:51.000000000 +0200 @@ -10,4 +10,35 @@ ## Reporting a Vulnerability -We have enabled private reporting in GitHub, so please [follow these steps](https://github.com/hughsie/libxmlb/security) to report vulnerabilities. +If you find a vulnerability in libxmlb you should let us know using a +[private vulnerability disclosure](https://github.com/hughsie/libxmlb/security/advisories/new) on +GitHub, with a description of the issue, the steps you took to create the issue, affected +versions, and, if known, mitigations for the issue. + +Failing that, please report the issue against the `libxmlb` component in Red Hat bugzilla, with the +security checkbox set. You should get a response within 3 days. We have no bug bounty program, but +we're happy to credit you in updates if this is what you would like us to do. + +Security bugs found or assisted by AI tools must also include two additional things: + +* A reproducer that clearly shows the vulnerability on an unmodified `xb-tool` binary that is + running with all the usual OS level protections. + +* A pull requests that fixes the security vulnerability and adds unit tests; the logic being that + if you're using an autonomous system to find a theoretical issue you should also have the common + courtesy to submit a PR that fixes the vulnerability. + +Any security issue with the premise of “an attacker can supply a crafted xmlb file” will be closed. +The `.xmlb` binary file is an internal-ABI **trusted** memory-mapped blob -- it is not a loadable +file format and cannot be used like that. No libxmlb user is shipping pre-compiled `.xmlb` blobs to +end users, and due to the implementation of the silo GUID it would be impossible to do so. + +Additionally, we will not issue CVEs or GHSA IDs for AI-discovered security issues lower than +moderate -- doing so offers nothing to the libxmlb community (anyone can use similar tools to find +the same issue) and adds a huge burden on the existing maintenance team. + +The CVSS scoring of reported bugs is often wildly inflated by AI tools (for various reasons), and +the actual CVSS scoring may be modified at the libxmlb maintainers discretion. + +So-called "low severity" security bugs or "hardening enhancements" will be treated as normal issues +and will be fixed as part of the next tarball release with no coordinated disclosure process. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/contrib/libxmlb.spec.in new/libxmlb-0.3.29/contrib/libxmlb.spec.in --- old/libxmlb-0.3.27/contrib/libxmlb.spec.in 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/contrib/libxmlb.spec.in 2026-07-27 17:01:51.000000000 +0200 @@ -1,6 +1,4 @@ -%bcond stemmer %{defined fedora} - -%global glib2_version 2.45.8 +%global glib2_version 2.56.0 %define alphatag #ALPHATAG# @@ -14,7 +12,7 @@ BuildRequires: glib2-devel >= %{glib2_version} BuildRequires: gtk-doc -%if %{with stemmer} +%if 0%{?fedora} BuildRequires: libstemmer-devel %endif BuildRequires: meson diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/meson.build new/libxmlb-0.3.29/meson.build --- old/libxmlb-0.3.27/meson.build 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/meson.build 2026-07-27 17:01:51.000000000 +0200 @@ -1,7 +1,7 @@ project('libxmlb', 'c', - version : '0.3.27', + version : '0.3.29', license : 'LGPL-2.1-or-later', - meson_version : '>=0.60.0', + meson_version : '>=0.58.2', default_options : ['warning_level=2', 'c_std=c99'], ) @@ -129,7 +129,7 @@ endif mandir = join_paths(prefix, get_option('mandir')) -gio = dependency('gio-2.0', version : '>= 2.68.0') +gio = dependency('gio-2.0', version : '>= 2.56.0') giounix = dependency('gio-unix-2.0', required: false) lzma = dependency('liblzma', required: get_option('lzma')) if lzma.found() @@ -143,12 +143,6 @@ conf.set('HAVE_GIO_UNIX', '1') endif -# Limit our use of GLib API to our minimum version requirement, and what’s -# available in RHEL 9. Use of more modern API has to be optional and -# protected by GLIB_CHECK_VERSION. -add_project_arguments('-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_46', language: 'c') -add_project_arguments('-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_68', language: 'c') - libxmlb_deps = [ gio, ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/meson_options.txt new/libxmlb-0.3.29/meson_options.txt --- old/libxmlb-0.3.27/meson_options.txt 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/meson_options.txt 2026-07-27 17:01:51.000000000 +0200 @@ -10,8 +10,4 @@ option('zstd', type: 'feature', description: 'enable zstd support', - deprecated: { - 'true': 'enabled', - 'false': 'disabled', - }, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/meson.build new/libxmlb-0.3.29/src/meson.build --- old/libxmlb-0.3.27/src/meson.build 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/meson.build 2026-07-27 17:01:51.000000000 +0200 @@ -6,7 +6,7 @@ install_headers( 'xmlb.h', - subdir : 'libxmlb-2', + subdir : 'libxmlb-@0@'.format(lt_current), ) xb_headers = files( @@ -16,6 +16,7 @@ 'xb-builder-source.h', 'xb-builder-source-ctx.h', 'xb-compile.h', + 'xb-compile-glib-2-62.h', 'xb-machine.h', 'xb-node.h', 'xb-node-query.h', @@ -33,7 +34,7 @@ install_headers( xb_headers, - subdir : 'libxmlb-2/libxmlb', + subdir : 'libxmlb-@0@/libxmlb'.format(lt_current), ) subdir('libxmlb') @@ -138,7 +139,7 @@ pkgg = import('pkgconfig') pkgg.generate(libxmlb, requires : [ 'gio-2.0' ], - subdirs : 'libxmlb-2', + subdirs : 'libxmlb-@0@'.format(lt_current), version : meson.project_version(), name : 'libxmlb', filebase : 'xmlb', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-builder-source-ctx.c new/libxmlb-0.3.29/src/xb-builder-source-ctx.c --- old/libxmlb-0.3.27/src/xb-builder-source-ctx.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-builder-source-ctx.c 2026-07-27 17:01:51.000000000 +0200 @@ -70,9 +70,9 @@ g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, - "cannot read from fd: 0x%x > 0x%x", + "cannot read from fd: 0x%x > 0x%zx", buf->len, - (guint)count); + count); return NULL; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-builder-source.c new/libxmlb-0.3.29/src/xb-builder-source.c --- old/libxmlb-0.3.27/src/xb-builder-source.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-builder-source.c 2026-07-27 17:01:51.000000000 +0200 @@ -469,7 +469,7 @@ g_debug("detected content type of %s to be %s", basename, content_type); if (content_type == NULL) return NULL; - if (g_strcmp0(content_type, "application/xml") == 0) + if (g_content_type_is_a(content_type, "application/xml")) break; /* Also accept the text/xml alias, just in case the user’s content-type database is * slightly broken (application/xml should normally be what’s used): */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-builder.c new/libxmlb-0.3.29/src/xb-builder.c --- old/libxmlb-0.3.27/src/xb-builder.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-builder.c 2026-07-27 17:01:51.000000000 +0200 @@ -869,11 +869,9 @@ /* the builder needs to know the locales */ if (priv->locales->len == 0 && (flags & XB_BUILDER_COMPILE_FLAG_NATIVE_LANGS)) { - g_set_error_literal(error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "No locales set and using NATIVE_LANGS"); - return NULL; + const gchar *const *locales = g_get_language_names(); + for (guint i = 0; locales[i] != NULL; i++) + xb_builder_add_locale(self, locales[i]); } /* create helper used for compiling */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-compile-glib-2-62.h new/libxmlb-0.3.29/src/xb-compile-glib-2-62.h --- old/libxmlb-0.3.27/src/xb-compile-glib-2-62.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libxmlb-0.3.29/src/xb-compile-glib-2-62.h 2026-07-27 17:01:51.000000000 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright 2026 Richard Hughes <[email protected]> + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#include <glib.h> + +typedef void GRWLockReaderLocker; + +static inline GRWLockReaderLocker * +g_rw_lock_reader_locker_new(GRWLock *rw_lock) +{ + g_rw_lock_reader_lock(rw_lock); + return (GRWLockReaderLocker *)rw_lock; +} + +static inline void +g_rw_lock_reader_locker_free(GRWLockReaderLocker *locker) +{ + g_rw_lock_reader_unlock((GRWLock *)locker); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GRWLockReaderLocker, g_rw_lock_reader_locker_free) + +typedef void GRWLockWriterLocker; + +static inline GRWLockWriterLocker * +g_rw_lock_writer_locker_new(GRWLock *rw_lock) +{ + g_rw_lock_writer_lock(rw_lock); + return (GRWLockWriterLocker *)rw_lock; +} + +static inline void +g_rw_lock_writer_locker_free(GRWLockWriterLocker *locker) +{ + g_rw_lock_writer_unlock((GRWLock *)locker); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GRWLockWriterLocker, g_rw_lock_writer_locker_free) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-compile.h new/libxmlb-0.3.29/src/xb-compile.h --- old/libxmlb-0.3.27/src/xb-compile.h 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-compile.h 2026-07-27 17:01:51.000000000 +0200 @@ -16,3 +16,7 @@ #define G_GNUC_NON_NULL(params...) #endif #endif + +#if !GLIB_CHECK_VERSION(2, 62, 0) +#include "xb-compile-glib-2-62.h" +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-machine.c new/libxmlb-0.3.29/src/xb-machine.c --- old/libxmlb-0.3.27/src/xb-machine.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-machine.c 2026-07-27 17:01:51.000000000 +0200 @@ -1011,7 +1011,7 @@ kind == XB_OPCODE_KIND_BOUND_INDEXED_TEXT || kind == XB_OPCODE_KIND_BOUND_INTEGER)) { XbOpcode *machine_opcode; - if (!xb_machine_stack_push(self, stack, &machine_opcode, error)) + if (!xb_stack_push(stack, &machine_opcode, error)) return FALSE; if (!xb_value_bindings_lookup_opcode(bindings, bound_opcode_idx++, @@ -1061,7 +1061,7 @@ kind == XB_OPCODE_KIND_BOUND_INDEXED_TEXT || kind == XB_OPCODE_KIND_BOUND_INTEGER))) { XbOpcode *machine_opcode; - if (!xb_machine_stack_push(self, stack, &machine_opcode, error)) + if (!xb_stack_push(stack, &machine_opcode, error)) return FALSE; *machine_opcode = *opcode; machine_opcode->destroy_func = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-opcode.c new/libxmlb-0.3.29/src/xb-opcode.c --- old/libxmlb-0.3.27/src/xb-opcode.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-opcode.c 2026-07-27 17:01:51.000000000 +0200 @@ -357,7 +357,7 @@ self->val = val; self->tokens_len = 0; self->destroy_func = destroy_func; - memset(self->tokens, 0, sizeof(self->tokens)); + self->tokens[0] = NULL; } /** @@ -466,6 +466,7 @@ if (self->tokens_len >= XB_OPCODE_TOKEN_MAX) return FALSE; self->tokens[self->tokens_len++] = val; + self->tokens[self->tokens_len] = NULL; self->kind |= XB_OPCODE_FLAG_TOKENIZED; return TRUE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-self-test.c new/libxmlb-0.3.29/src/xb-self-test.c --- old/libxmlb-0.3.27/src/xb-self-test.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-self-test.c 2026-07-27 17:01:51.000000000 +0200 @@ -2065,22 +2065,18 @@ static void xb_builder_strtab_ntags_limit_func(void) { - gboolean ret; g_autoptr(GError) error = NULL; - g_autoptr(GString) xml = g_string_new("<root>"); g_autoptr(XbBuilder) builder = xb_builder_new(); - g_autoptr(XbBuilderSource) source = xb_builder_source_new(); + g_autoptr(XbBuilderNode) root = xb_builder_node_new("root"); g_autoptr(XbSilo) silo = NULL; - /* generate XML with more than 65535 unique element names */ - for (guint i = 0; i <= G_MAXUINT16; i++) - g_string_append_printf(xml, "<e%u/>", i); - g_string_append(xml, "</root>"); + /* build a node tree with more than 65535 unique element names */ + for (guint i = 0; i <= G_MAXUINT16; i++) { + g_autofree gchar *name = g_strdup_printf("e%u", i); + xb_builder_node_insert_text(root, name, NULL, NULL); + } - ret = xb_builder_source_load_xml(source, xml->str, XB_BUILDER_SOURCE_FLAG_NONE, &error); - g_assert_no_error(error); - g_assert_true(ret); - xb_builder_import_source(builder, source); + xb_builder_import_node(builder, root); silo = xb_builder_compile(builder, XB_BUILDER_COMPILE_FLAG_NONE, NULL, &error); g_assert_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA); g_assert_null(silo); @@ -2345,23 +2341,6 @@ } static void -xb_builder_native_lang_no_locales_func(void) -{ - gboolean ret; - g_autoptr(GError) error = NULL; - g_autoptr(XbBuilder) builder = xb_builder_new(); - g_autoptr(XbSilo) silo = NULL; - - /* import from XML */ - ret = xb_test_import_xml(builder, "<id>gimp.desktop</id>", &error); - g_assert_no_error(error); - g_assert_true(ret); - silo = xb_builder_compile(builder, XB_BUILDER_COMPILE_FLAG_SINGLE_LANG, NULL, &error); - g_assert_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA); - g_assert_null(silo); -} - -static void xb_xpath_parent_func(void) { XbNode *n; @@ -3301,6 +3280,52 @@ g_print("query[x%u]: %.3fms\n", n_components, g_timer_elapsed(timer, NULL) * 1000); } +static void +xb_speed_precompiled_func(void) +{ + guint n_components = 5000; + g_autoptr(GError) error = NULL; + g_autoptr(GString) xml = g_string_new(NULL); + g_autoptr(GTimer) timer = g_timer_new(); + g_autoptr(XbSilo) silo = NULL; + g_autoptr(XbQuery) query = NULL; + +#ifdef __s390x__ + g_test_skip("s390 too slow, skipping"); + return; +#endif + + /* create a huge document */ + g_string_append(xml, "<components>"); + for (guint i = 0; i < n_components; i++) { + g_string_append(xml, "<component type=\"firmware\">"); + g_string_append_printf(xml, " <id>%06u.firmware</id>", i); + g_string_append(xml, " <name>ColorHug2</name>"); + g_string_append(xml, " <summary>Firmware</summary>"); + g_string_append(xml, "</component>"); + } + g_string_append(xml, "</components>"); + + silo = xb_silo_new_from_xml(xml->str, &error); + g_assert_no_error(error); + g_assert_nonnull(silo); + + query = xb_query_new(silo, "components/component[@type='firmware']", &error); + g_assert_no_error(error); + g_assert_nonnull(query); + + g_timer_reset(timer); + for (guint i = 0; i < n_components; i += 20) { + g_autoptr(GPtrArray) results = NULL; + results = xb_silo_query_full(silo, query, &error); + g_assert_no_error(error); + g_assert_nonnull(results); + if (i == 0) + g_assert_cmpint(results->len, ==, n_components); + } + g_print("query_full[x%u]: %.3fms\n", n_components, g_timer_elapsed(timer, NULL) * 1000); +} + int main(int argc, char **argv) { @@ -3332,8 +3357,6 @@ g_test_add_func("/libxmlb/builder{cdata}", xb_builder_cdata_func); g_test_add_func("/libxmlb/builder{native-lang}", xb_builder_native_lang_func); g_test_add_func("/libxmlb/builder{native-lang-nested}", xb_builder_native_lang2_func); - g_test_add_func("/libxmlb/builder{native-lang-locale}", - xb_builder_native_lang_no_locales_func); g_test_add_func("/libxmlb/builder{empty}", xb_builder_empty_func); g_test_add_func("/libxmlb/builder{ensure}", xb_builder_ensure_func); g_test_add_func("/libxmlb/builder{ensure-watch-source}", @@ -3382,6 +3405,7 @@ if (g_test_perf()) { g_test_add_func("/libxmlb/threading", xb_threading_func); g_test_add_func("/libxmlb/speed", xb_speed_func); + g_test_add_func("/libxmlb/speed-precompiled", xb_speed_precompiled_func); } return g_test_run(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-silo-node.c new/libxmlb-0.3.29/src/xb-silo-node.c --- old/libxmlb-0.3.27/src/xb-silo-node.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-silo-node.c 2026-07-27 17:01:51.000000000 +0200 @@ -11,8 +11,8 @@ xb_silo_node_to_string(const XbSiloNode *self) { GString *str = g_string_new("XbSiloNode:\n"); - g_string_append_printf(str, " flags: 0x%x\n", self->flags); - g_string_append_printf(str, " attr_count: %u\n", self->attr_count); + g_string_append_printf(str, " flags: 0x%x\n", (guint)self->flags); + g_string_append_printf(str, " attr_count: %u\n", (guint)self->attr_count); if (self->flags & XB_SILO_NODE_FLAG_IS_ELEMENT) { if (self->element_name != XB_SILO_UNSET) g_string_append_printf(str, " element_name: %u\n", self->element_name); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-silo-query.c new/libxmlb-0.3.29/src/xb-silo-query.c --- old/libxmlb-0.3.27/src/xb-silo-query.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-silo-query.c 2026-07-27 17:01:51.000000000 +0200 @@ -22,6 +22,50 @@ #define XB_QUERY_OR_BRANCH_MAX 64 +static inline gboolean +xb_silo_query_node_matches_predicate_with_bindings(XbSilo *self, + XbStack *opcodes, + XbSiloQueryData *query_data, + XbValueBindings *bindings, + guint *bindings_offset, + gboolean *result, + GError **error) +{ + XbMachine *machine = xb_silo_get_machine(self); + g_auto(XbValueBindings) predicate_bindings = XB_VALUE_BINDINGS_INIT(); + guint predicate_bindings_idx = 0; + XbValueBindings *predicate_bindings_ptr = &predicate_bindings; + + /* set up the bindings for this predicate */ + for (guint k = 0; k < xb_stack_get_size(opcodes); k++) { + XbOpcode *op = xb_stack_peek(opcodes, k); + if (xb_opcode_is_binding(op)) { + /* ignore errors as they’ll be caught by xb_machine_run() */ + xb_value_bindings_copy_binding(bindings, + *bindings_offset + predicate_bindings_idx, + &predicate_bindings, + predicate_bindings_idx); + predicate_bindings_idx++; + } + } + + /* run the predicate; pass NULL for the bindings iff + * (bindings == NULL), as that means we’ve been called + * with pre-0.3.0-style pre-bound values */ + if (!xb_machine_run_with_bindings(machine, + opcodes, + predicate_bindings_ptr, + result, + query_data, + error)) + return FALSE; + + *bindings_offset += predicate_bindings_idx; + + /* success */ + return TRUE; +} + static gboolean xb_silo_query_node_matches(XbSilo *self, XbMachine *machine, @@ -48,39 +92,26 @@ if (section->predicates != NULL) { for (guint i = 0; i < section->predicates->len; i++) { XbStack *opcodes = g_ptr_array_index(section->predicates, i); - g_auto(XbValueBindings) predicate_bindings = XB_VALUE_BINDINGS_INIT(); - guint predicate_bindings_idx = 0; - XbValueBindings *predicate_bindings_ptr = NULL; - - if (bindings != NULL) - predicate_bindings_ptr = &predicate_bindings; - - /* set up the bindings for this predicate */ - for (guint k = 0; bindings != NULL && k < xb_stack_get_size(opcodes); k++) { - XbOpcode *op = xb_stack_peek(opcodes, k); - if (xb_opcode_is_binding(op)) { - /* ignore errors as they’ll be caught by xb_machine_run() */ - xb_value_bindings_copy_binding(bindings, - bindings_offset + - predicate_bindings_idx, - &predicate_bindings, - predicate_bindings_idx); - predicate_bindings_idx++; - } + if (bindings != NULL) { + if (!xb_silo_query_node_matches_predicate_with_bindings( + self, + opcodes, + query_data, + bindings, + &bindings_offset, + result, + error)) + return FALSE; + } else { + /* we’ve been called with pre-0.3.0-style pre-bound values */ + if (!xb_machine_run_with_bindings(machine, + opcodes, + NULL, + result, + query_data, + error)) + return FALSE; } - - /* run the predicate; pass NULL for the bindings iff - * (bindings == NULL), as that means we’ve been called - * with pre-0.3.0-style pre-bound values */ - if (!xb_machine_run_with_bindings(machine, - opcodes, - predicate_bindings_ptr, - result, - query_data, - error)) - return FALSE; - - bindings_offset += predicate_bindings_idx; } } @@ -106,32 +137,56 @@ XB_SILO_QUERY_HELPER_NONE = 0, XB_SILO_QUERY_HELPER_USE_SN = 1 << 0, XB_SILO_QUERY_HELPER_FORCE_NODE_CACHE = 1 << 1, + XB_SILO_QUERY_HELPER_USE_HASH = 1 << 2, } XbSiloQueryHelperFlags; typedef struct { - GPtrArray *sections; /* of XbQuerySection */ - GPtrArray *results; /* of XbNode or XbSiloNode (see @flags) */ + GPtrArray *sections; /* of XbQuerySection */ + GPtrArray *nodes; /* of XbNode or XbSiloNode (see @flags) */ + GHashTable *nodes_hash; /* of sn:1 */ XbValueBindings *bindings; - GHashTable *results_hash; /* of sn:1 */ guint limit; XbSiloQueryHelperFlags flags; XbSiloQueryData *query_data; } XbSiloQueryHelper; +static void +xb_silo_query_helper_free(XbSiloQueryHelper *helper) +{ + if (helper->nodes != NULL) + g_ptr_array_unref(helper->nodes); + if (helper->nodes_hash != NULL) + g_hash_table_unref(helper->nodes_hash); +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(XbSiloQueryHelper, xb_silo_query_helper_free) + static gboolean -xb_silo_query_section_add_result(XbSilo *self, XbSiloQueryHelper *helper, XbSiloNode *sn) +xb_silo_query_section_add_node(XbSilo *self, XbSiloQueryHelper *helper, XbSiloNode *sn) { - if (g_hash_table_lookup(helper->results_hash, sn) != NULL) - return FALSE; + if (helper->flags & XB_SILO_QUERY_HELPER_USE_HASH) { + if (helper->nodes_hash == NULL) { + helper->nodes_hash = g_hash_table_new(g_direct_hash, g_direct_equal); + } else { + if (g_hash_table_lookup(helper->nodes_hash, sn) != NULL) + return FALSE; + } + g_hash_table_add(helper->nodes_hash, sn); + } if (helper->flags & XB_SILO_QUERY_HELPER_USE_SN) { - g_ptr_array_add(helper->results, sn); + if (helper->nodes == NULL) + helper->nodes = g_ptr_array_new(); + g_ptr_array_add(helper->nodes, sn); } else { gboolean force_node_cache = (helper->flags & XB_SILO_QUERY_HELPER_FORCE_NODE_CACHE) > 0; - g_ptr_array_add(helper->results, xb_silo_create_node(self, sn, force_node_cache)); + if (helper->nodes == NULL) { + helper->nodes = + g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref); + } + g_ptr_array_add(helper->nodes, xb_silo_create_node(self, sn, force_node_cache)); } - g_hash_table_add(helper->results_hash, sn); - return helper->results->len == helper->limit; + return helper->limit > 0 && helper->nodes->len >= helper->limit; } /* @@ -163,7 +218,7 @@ if (parent == NULL) return FALSE; if (i == helper->sections->len - 1) { - xb_silo_query_section_add_result(self, helper, parent); + xb_silo_query_section_add_node(self, helper, parent); return TRUE; } return xb_silo_query_section_root(self, @@ -212,7 +267,7 @@ return FALSE; if (result) { if (i == helper->sections->len - 1) { - if (xb_silo_query_section_add_result(self, helper, sn)) + if (xb_silo_query_section_add_node(self, helper, sn)) break; } else { if (!xb_silo_query_section_root(self, @@ -222,8 +277,7 @@ helper, error)) return FALSE; - if (helper->results->len > 0 && - helper->results->len == helper->limit) + if (helper->nodes != NULL && helper->nodes->len == helper->limit) break; } } @@ -249,35 +303,28 @@ static gboolean xb_silo_query_part(XbSilo *self, XbSiloNode *sroot, - GPtrArray *results, - GHashTable *results_hash, + XbSiloQueryHelper *helper, XbQuery *query, XbQueryContext *context, gboolean first_result_only, - XbSiloQueryData *query_data, - XbSiloQueryHelperFlags flags, GError **error) { - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - XbSiloQueryHelper helper = { - .results = results, - .bindings = (context != NULL) ? xb_query_context_get_bindings(context) : NULL, - .limit = first_result_only ? 1 - : (context != NULL) ? xb_query_context_get_limit(context) - : xb_query_get_limit(query), - .flags = flags, - .results_hash = results_hash, - .query_data = query_data, - }; - XbQueryFlags query_flags = (context != NULL) ? xb_query_context_get_flags(context) - : xb_query_get_flags(query); - G_GNUC_END_IGNORE_DEPRECATIONS + if (context != NULL) { + if (xb_query_context_get_flags(context) & XB_QUERY_FLAG_FORCE_NODE_CACHE) + helper->flags |= XB_SILO_QUERY_HELPER_FORCE_NODE_CACHE; + helper->bindings = xb_query_context_get_bindings(context); + helper->limit = first_result_only ? 1 : xb_query_context_get_limit(context); + } else { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + if (xb_query_get_flags(query) & XB_QUERY_FLAG_FORCE_NODE_CACHE) + helper->flags |= XB_SILO_QUERY_HELPER_FORCE_NODE_CACHE; + helper->limit = first_result_only ? 1 : xb_query_get_limit(query); + G_GNUC_END_IGNORE_DEPRECATIONS + } /* find each section */ - helper.sections = xb_query_get_sections(query); - if (query_flags & XB_QUERY_FLAG_FORCE_NODE_CACHE) - helper.flags |= XB_SILO_QUERY_HELPER_FORCE_NODE_CACHE; - return xb_silo_query_section_root(self, sroot, 0, 0, &helper, error); + helper->sections = xb_query_get_sections(query); + return xb_silo_query_section_root(self, sroot, 0, 0, helper, error); } /* Returns an array with (element-type XbSiloNode) if @@ -292,13 +339,12 @@ { XbSiloNode *sn = NULL; g_auto(GStrv) split = NULL; - g_autoptr(GHashTable) results_hash = g_hash_table_new(g_direct_hash, g_direct_equal); - g_autoptr(GPtrArray) results = NULL; g_autoptr(GTimer) timer = xb_silo_start_profile(self); XbSiloQueryData query_data = { .sn = NULL, .position = 0, }; + g_auto(XbSiloQueryHelper) helper = {.flags = flags, .query_data = &query_data}; g_return_val_if_fail(XB_IS_SILO(self), NULL); g_return_val_if_fail(xpath != NULL, NULL); @@ -310,11 +356,6 @@ return NULL; } - if (flags & XB_SILO_QUERY_HELPER_USE_SN) - results = g_ptr_array_new_with_free_func(NULL); - else - results = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref); - /* subtree query */ if (n != NULL) { sn = xb_node_get_sn(n); @@ -347,7 +388,7 @@ if (query == NULL) { if (g_error_matches(error_local, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT) && - (split[i + 1] != NULL || results->len > 0)) { + (split[i + 1] != NULL || helper.nodes != NULL)) { if (xb_silo_get_profile_flags(self) & XB_SILO_PROFILE_FLAG_DEBUG) { g_debug("ignoring for OR statement: %s", error_local->message); @@ -362,18 +403,8 @@ } xb_query_context_set_limit(&context, limit); - if (!xb_silo_query_part(self, - sn, - results, - results_hash, - query, - &context, - FALSE, - &query_data, - flags, - error)) { + if (!xb_silo_query_part(self, sn, &helper, query, &context, FALSE, error)) return NULL; - } } /* profile */ @@ -384,11 +415,11 @@ n != NULL ? xb_node_get_element(n) : "/", xpath, limit, - results->len); + helper.nodes != NULL ? helper.nodes->len : 0); } /* nothing found */ - if (results->len == 0) { + if (helper.nodes == NULL) { g_set_error(error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, @@ -396,7 +427,7 @@ xpath); return NULL; } - return g_steal_pointer(&results); + return g_steal_pointer(&helper.nodes); } /** @@ -489,14 +520,15 @@ GError **error) { XbSiloNode *sn = NULL; - g_autoptr(GHashTable) results_hash = g_hash_table_new(g_direct_hash, g_direct_equal); - g_autoptr(GPtrArray) results = - g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref); g_autoptr(GTimer) timer = xb_silo_start_profile(self); XbSiloQueryData query_data = { .sn = NULL, .position = 0, }; + g_auto(XbSiloQueryHelper) helper = { + .flags = first_result_only ? XB_SILO_QUERY_HELPER_NONE : XB_SILO_QUERY_HELPER_USE_HASH, + .query_data = &query_data, + }; G_GNUC_BEGIN_IGNORE_DEPRECATIONS XbQueryFlags query_flags = (context != NULL) ? xb_query_context_get_flags(context) : xb_query_get_flags(query); @@ -519,17 +551,9 @@ if (n != NULL) sn = xb_node_get_sn(n); - /* only one query allowed */ - if (!xb_silo_query_part(self, - sn, - results, - results_hash, - query, - context, - first_result_only, - &query_data, - XB_SILO_QUERY_HELPER_NONE, - error)) + /* only one query, so dedup is only needed for multi-result queries + * where parent traversal could fan in to the same node */ + if (!xb_silo_query_part(self, sn, &helper, query, context, first_result_only, error)) return NULL; /* profile */ @@ -554,27 +578,21 @@ tmp, bindings_str != NULL ? bindings_str : "", limit, - results->len); + helper.nodes != NULL ? helper.nodes->len : 0); } /* nothing found */ - if (results->len == 0) { - if (error != NULL) { - g_autofree gchar *tmp = xb_query_to_string(query); - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "no results for XPath query '%s'", - tmp); - } + if (helper.nodes == NULL) { + if (error != NULL) + g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "no results"); return NULL; } /* reverse order */ if (query_flags & XB_QUERY_FLAG_REVERSE) - _g_ptr_array_reverse(results); + _g_ptr_array_reverse(helper.nodes); - return g_steal_pointer(&results); + return g_steal_pointer(&helper.nodes); } /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-silo.c new/libxmlb-0.3.29/src/xb-silo.c --- old/libxmlb-0.3.27/src/xb-silo.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-silo.c 2026-07-27 17:01:51.000000000 +0200 @@ -53,6 +53,7 @@ guint32 strtab; GHashTable *strtab_tags; GHashTable *strindex; + GRWLock strindex_mutex; gboolean enable_node_cache; GHashTable *nodes; /* (mutex nodes_mutex) */ GMutex nodes_mutex; @@ -199,11 +200,13 @@ { XbSiloPrivate *priv = GET_PRIVATE(self); const gchar *tmp; + g_autoptr(GRWLockWriterLocker) locker_rw = NULL; /* get the string version */ tmp = xb_silo_from_strtab(self, offset, error); if (tmp == NULL) return FALSE; + locker_rw = g_rw_lock_writer_locker_new(&priv->strindex_mutex); if (g_hash_table_lookup(priv->strindex, tmp) != NULL) return TRUE; g_hash_table_insert(priv->strindex, (gpointer)tmp, GUINT_TO_POINTER(offset)); @@ -216,6 +219,9 @@ { XbSiloPrivate *priv = GET_PRIVATE(self); gpointer val = NULL; + g_autoptr(GRWLockReaderLocker) locker_ro = NULL; + + locker_ro = g_rw_lock_reader_locker_new(&priv->strindex_mutex); if (!g_hash_table_lookup_extended(priv->strindex, str, NULL, &val)) return XB_SILO_UNSET; return GPOINTER_TO_INT(val); @@ -266,8 +272,8 @@ g_set_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "blob too small: 0x%x", - (guint)g_bytes_get_size(priv->blob)); + "blob too small: 0x%zx", + g_bytes_get_size(priv->blob)); return NULL; } if (G_UNLIKELY(g_bytes_get_size(priv->blob) == sizeof(XbSiloHeader))) { @@ -726,7 +732,6 @@ xb_silo_get_machine(XbSilo *self) { XbSiloPrivate *priv = GET_PRIVATE(self); - g_return_val_if_fail(XB_IS_SILO(self), NULL); return priv->machine; } @@ -759,6 +764,7 @@ g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* no longer valid */ + xb_silo_invalidate(self); if (priv->enable_node_cache) { locker = g_mutex_locker_new(&priv->nodes_mutex); if (priv->nodes != NULL) @@ -766,8 +772,17 @@ } g_hash_table_remove_all(priv->strtab_tags); + + g_rw_lock_writer_lock(&priv->strindex_mutex); + g_hash_table_remove_all(priv->strindex); + g_rw_lock_writer_unlock(&priv->strindex_mutex); + g_clear_pointer(&priv->guid, g_free); + g_rw_lock_writer_lock(&priv->query_cache_mutex); + g_hash_table_remove_all(priv->query_cache); + g_rw_lock_writer_unlock(&priv->query_cache_mutex); + /* refcount internally */ if (priv->blob != NULL) g_bytes_unref(priv->blob); @@ -848,7 +863,7 @@ xb_silo_add_profile(self, timer, "parse blob"); /* success */ - priv->valid = TRUE; + xb_silo_uninvalidate(self); return TRUE; } @@ -1753,6 +1768,7 @@ priv->strtab_tags = g_hash_table_new(g_str_hash, g_str_equal); priv->strindex = g_hash_table_new(g_str_hash, g_str_equal); + g_rw_lock_init(&priv->strindex_mutex); priv->profile_str = g_string_new(NULL); priv->query_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); g_rw_lock_init(&priv->query_cache_mutex); @@ -1827,6 +1843,7 @@ g_rw_lock_clear(&priv->query_cache_mutex); g_object_unref(priv->machine); g_hash_table_unref(priv->strindex); + g_rw_lock_clear(&priv->strindex_mutex); g_hash_table_unref(priv->file_monitors); g_mutex_clear(&priv->file_monitors_mutex); g_hash_table_unref(priv->strtab_tags); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-string.h new/libxmlb-0.3.29/src/xb-string.h --- old/libxmlb-0.3.27/src/xb-string.h 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-string.h 2026-07-27 17:01:51.000000000 +0200 @@ -13,8 +13,6 @@ void xb_string_append_union(GString *xpath, const gchar *fmt, ...) G_GNUC_PRINTF(2, 3) G_GNUC_NON_NULL(1); - -GLIB_DEPRECATED_FOR(xb_value_bindings_bind_str) gchar * xb_string_escape(const gchar *str) G_GNUC_NON_NULL(1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libxmlb-0.3.27/src/xb-value-bindings.c new/libxmlb-0.3.29/src/xb-value-bindings.c --- old/libxmlb-0.3.27/src/xb-value-bindings.c 2026-05-18 17:44:22.000000000 +0200 +++ new/libxmlb-0.3.29/src/xb-value-bindings.c 2026-07-27 17:01:51.000000000 +0200 @@ -70,13 +70,11 @@ { RealValueBindings *_self = (RealValueBindings *)self; - g_return_if_fail(idx < G_N_ELEMENTS(_self->values)); - - if (_self->values[idx].ptr != NULL && _self->values[idx].destroy_func) + if (_self->values[idx].ptr != NULL && _self->values[idx].destroy_func) { _self->values[idx].destroy_func(_self->values[idx].ptr); - _self->values[idx].kind = XB_BOUND_VALUE_KIND_NONE; - _self->values[idx].ptr = NULL; - _self->values[idx].destroy_func = NULL; + _self->values[idx].ptr = NULL; + _self->values[idx].destroy_func = NULL; + } } /**
