Skip to main content

the avatar of Federico Mena-Quintero

Mutation testing for librsvg

I was reading a blog post about the testing strategy for the Wild linker, when I came upon a link to cargo-mutants, a mutation testing tool for Rust. The tool promised to be easy to set up, so I gave it a try. I'm happy to find that it totally delivers!

Briefly: mutation testing catches cases where bugs are deliberately inserted in the source code, but the test suite fails to catch them: after making the incorrect changes, all the tests still pass. This indicates a gap in the test suite.

Previously I had only seen mentions of "mutation testing" in passing, as something exotic to be done when testing compilers. I don't recall seeing it as a general tool; maybe I have not been looking closely enough.

Setup and running

Setting up cargo-mutants is easy enough: you can cargo install cargo-mutants and run it with cargo mutants.

For librsvg this ran for a few hours, but I discovered a couple of things related to the way the librsvg repository is structured. The repo is a cargo workspace with multiple crates: the librsvg implementation and public Rust API, the rsvg-convert binary, and some utilities like rsvg-bench.

  1. By default cargo-mutants only seemed to pick up the tests for rsvg-convert. I think it may have done this because it is the only binary in the workspace that has a test suite (e.g. rsvg-bench does not have a test suite).

  2. I had to run cargo mutants --package librsvg to tell it to consider the test suite for the librsvg crate, which is the main library. I think I could have used cargo mutants --workspace to make it run all the things; maybe I'll try that next time.

Initial results

My initial run on rsvg-covert produced useful results; cargo-mutants found 32 mutations in the rsvg-convert source code that ought to have caused failures, but the test suite didn't catch them.

The running output of cargo-mutants on the librsvg

The second run, on the librsvg crate, took about 10 hours. It is fascinating to watch it run. In the end it found 889 mutations with bugs that the test suite couldn't catch:

5243 mutants tested in 9h 53m 15s: 889 missed, 3663 caught, 674 unviable, 17 timeouts

What does that mean?

  • 5243 mutants tested: how many modifications were tried on the code.

  • 889 missed: The important ones: after a modification was made, the test suite failed to catch this modification.

  • 3663 caught: Good! The test suite caught these!

  • 674 unviable: These modifications didn't compile. Nothing to do.

  • 17 timeouts: Worth investigating; maybe a function can be marked to be skipped for mutation.

Starting to analyze the results

Due to the way cargo-mutants works, the "missed" results come in an arbitrary order, spread among all the source files:

rsvg/src/path_parser.rs:857:9: replace <impl fmt::Display for ParseError>::fmt -> fmt::Result with Ok(Default::default())
rsvg/src/drawing_ctx.rs:732:33: replace > with == in DrawingCtx::check_layer_nesting_depth
rsvg/src/filters/lighting.rs:931:16: replace / with * in Normal::bottom_left
rsvg/src/test_utils/compare_surfaces.rs:24:9: replace <impl fmt::Display for BufferDiff>::fmt -> fmt::Result with Ok(Default::default())
rsvg/src/filters/turbulence.rs:133:22: replace - with / in setup_seed
rsvg/src/document.rs:627:24: replace match guard is_mime_type(x, "image", "svg+xml") with false in ResourceType::from
rsvg/src/length.rs:472:57: replace * with + in CssLength<N, V>::to_points

So, I started by sorting the missed.txt file from the results. This is much better:

rsvg/src/accept_language.rs:136:9: replace AcceptLanguage::any_matches -> bool with false
rsvg/src/accept_language.rs:136:9: replace AcceptLanguage::any_matches -> bool with true
rsvg/src/accept_language.rs:78:9: replace <impl fmt::Display for AcceptLanguageError>::fmt -> fmt::Result with Ok(Default::default())
rsvg/src/angle.rs:40:22: replace < with <= in Angle::bisect
rsvg/src/angle.rs:41:56: replace - with + in Angle::bisect
rsvg/src/angle.rs:49:35: replace + with - in Angle::flip
rsvg/src/angle.rs:57:23: replace < with <= in Angle::normalize

With the sorted results, I can clearly see how cargo-mutants gradually does its modifications on (say) all the arithmetic and logic operators to try to find changes that would not be caught by the test suite.

Look at the first two lines from above, the ones that refer to AcceptLanguage::any_matches:

rsvg/src/accept_language.rs:136:9: replace AcceptLanguage::any_matches -> bool with false
rsvg/src/accept_language.rs:136:9: replace AcceptLanguage::any_matches -> bool with true

Now look at the corresponding lines in the source:

... impl AcceptLanguage {
135     fn any_matches(&self, tag: &LanguageTag) -> bool {
136         self.iter().any(|(self_tag, _weight)| tag.matches(self_tag))
137     }
... }
}

The two lines from missed.txt mean that if the body of this any_matches() function were replaced with just true or false, instead of its actual work, there would be no failed tests:

135     fn any_matches(&self, tag: &LanguageTag) -> bool {
136         false // or true, either version wouldn't affect the tests
137     }
}

This is bad! It indicates that the test suite does not check that this function, or the surrounding code, is working correctly. And yet, the test coverage report for those lines shows that they are indeed getting executed by the test suite. What is going on?

I think this is what is happening:

  • The librsvg crate's tests do not have tests for AcceptLanguage::any_matches.
  • The rsvg_convert crate's integration tests do have a test for its --accept-language option, and that is what causes this code to get executed and shown as covered in the coverage report.
  • This run of cargo-mutants was just for the librsvg crate, not for the integrated librsvg plus rsvg_convert.

Getting a bit pedantic with the purpose of tests, rsvg-convert assumes that the underlying librsvg library works correctly. The library advertises support in its API for matching based on AcceptLanguage, even though it doesn't test it internally.

On the other hand, rsvg-convert has a test for its own --accept-language option, in the sense of "did we implement this command-line option correctly", not in the sense of "does librsvg implement the AcceptLanguage functionality correctly".

After adding a little unit test for AcceptLanguage::any_matches in the librsvg crate, we can run cargo-mutants just for that the accept_language.rs file again:

# cargo mutants --package librsvg --file accept_language.rs
Found 37 mutants to test
ok       Unmutated baseline in 24.9s build + 6.1s test
 INFO Auto-set test timeout to 31s
MISSED   rsvg/src/accept_language.rs:78:9: replace <impl fmt::Display for AcceptLanguageError>::fmt -> fmt::Result with Ok(Default::default()) in 4.8s build + 6.5s test
37 mutants tested in 2m 59s: 1 missed, 26 caught, 10 unviable

Great! As expected, we just have 1 missed mutant on that file now. Let's look into it.

The function in question is now <impl fmt::Display for AcceptLanguageError>::fmt, an error formatter for the AcceptLanguageError type:

impl fmt::Display for AcceptLanguageError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::NoElements => write!(f, "no language tags in list"),
            Self::InvalidCharacters => write!(f, "invalid characters in language list"),
            Self::InvalidLanguageTag(e) => write!(f, "invalid language tag: {e}"),
            Self::InvalidWeight => write!(f, "invalid q= weight"),
        }
    }
}

What cargo-mutants means by "replace ... -> fmt::Result with Ok(Default::default()) is that if this function were modified to just be like this:

impl fmt::Display for AcceptLanguageError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(Default::default())
    }
}

then no tests would catch that. Now, this is just a formatter function; the fmt::Result it returns is just whether the underlying call to write!() succeeded. When cargo-mutants discovers that it can change this function to return Ok(Default::default()) it is because fmt::Result is defined as Result<(), fmt::Error>, which implements Default because the unit type () implements Default.

In librsvg, those AcceptLanguageError errors are just surfaced as strings for rsvg-convert, so that if you give it a command-line argument with an invalid value like --accept-language=foo, it will print the appropriate error. However, rsvg-convert does not make any promises as to the content of error messages, so I think it is acceptable to not test this error formatter — just to make sure it handles all the cases, which is already guaranteed by its match statement. Rationale:

  • There already are tests to ensure that the error codes are computed correctly in the parser for AcceptLanguage; those are the AcceptLanguageError's enumeration variants.

  • There is a test in rsvg-convert's test suite to ensure that it detects invalid language tags and reports them.

For cases like this, cargo-mutants allows marking code to be skipped. After marking this fmt implementation with #[mutants::skip], there are no more missed mutants in accept_language.rs.

Yay!

Understanding the tool

You should absolutely read "using results" in the cargo-mutants documentation, which is very well-written. It gives excellent suggestions for how to deal with missed mutants. Again, these indicate potential gaps in your test suite. The documentation discusses how to think about what to do, and I found it very helpful.

Then you should read about genres of mutants. It tells you the kind of modifications that cargo-mutants does to your code. Apart from changing individual operators to try to compute incorrect results, it also does things like replacing whole function bodies to return a different value instead. What if a function returns Default::default() instead of your carefully computed value? What if a boolean function always returns true? What if a function that returns a HashMap always returns an empty hash table, or one full with the product of all keys and values? That is, do your tests actually check your invariants, or your assumptions about the shape of the results of computations? It is really interesting stuff!

Future work for librsvg

The documentation for cargo-mutants suggests how to use it in CI, to ensure that no uncaught mutants are merged into the code. I will probably investigate this once I have fixed all the missed mutants; this will take me a few weeks at least.

Librsvg already has the gitlab incantation to show test coverage for patches in merge requests, so it would be nice to know if the existing tests, or any new added tests, are missing any conditions in the MR. That can be caught with cargo-mutants.

Hackery relevant to my tests, but not to this article

If you are just reading about mutation testing, you can ignore this section. If you are interested in the practicalities of compilation, read on!

The source code for the librsvg crate uses a bit of conditional compilation to select whether to export functions that are used by the integration tests as well as the crate's internal tests. For example, there is some code for diffing two images, and this is used when comparing the pixel output of rendering an SVG to a reference image. For historical reasons, this code ended up in the main library, so that it can run its own internal tests, but then the rest of the integration tests also use this code to diff images. The librsvg crate exports the "diff two images" functions only if it is being compiled for the integration tests, and it doesn't export them for a normal build of the public API.

Somehow, cargo-mutants didn't understand this, and the integration tests did not build since the cargo feature to select that conditionally-compiled code... wasn't active, or something. I tried enabling it by hand with something like cargo mutants --package librsvg -- --features test-utils but that still didn't work.

So, I hacked up a temporary version of the source tree just for mutation testing, which always exports the functions for diffing images, without conditional compilation. In the future it might be possible to split out that code to a separate crate that is only used where needed and never exported. I am not sure how it would be structured, since that code also depends on librsvg's internal representation of pixel images. Maybe we can move the whole thing out to a separate crate? Stop using Cairo image surfaces as the way to represent pixel images? Who knows!

the avatar of openSUSE News

Tumbleweed Monthly Update - November 2025

Software package updates for openSUSE Tumbleweed in November had a steady rhythm and delivered both user-visible improvements and deeper technical fixes across the stack.

Plasma 6.5.3 and KDE Gear 25.08.3 focused on stability and polish across the KDE desktop and applications, while GNOME 49.2 delivered smoother session behavior, fewer freezes and more reliable system handling. The rolling release moved forward with Kernel Source 6.17.9, Mesa 25.3.0, and PipeWire 1.5.83 and several other important updates. Security fixes were also widespread this month, spanning the kernel, X.Org Server, Firefox, grub2, OpenEXR, and multiple networking components.

As always, be sure to roll back using snapper if any issues arise.

For more details on the change logs for the month, visit the openSUSE Factory mailing list.

New Features and Enhancements

Plasma 6.5.3 and 6.5.2: The 6.5.3 update focuses on polish and stability across the desktop. KWin receives numerous fixes, including proper scaling in window screenshots, improved DRM handling after suspend, and better X11 test isolation, while also resolving popup activation and blur contrast issues. Breeze and breeze-gtk address visual glitches in menus and GTK4 app theming, such as missing expander arrows and incorrect corner radii. The 6.5.2 update provided fixes across core components like Discover, which now correctly handles firmware packages on certain distributions. KWin resolves crashes, improves screencast cleanup, fixes cursor and clipboard behavior under Xwayland, and addresses display issues with the FPS plugin and screenshot tool. Additional fixes include improved applet stability in Plasma Addons, better mobile task switching, proper timezone translation handling, and enhanced logging in plasma-welcome.

KDE Gear 25.08.3: Dolphin resolves issues with zoom reset, middle-click opening, and split view sizing, while Kdenlive fixes crashes related to clip pasting and monitor switching, along with improving image sequence detection and subtitle styling. Kate addresses focus and documentation handling in its LSP plugin, Itinerary and Kitinerary add new transport ticket extractors (including Comboios de Portugal and Wiener Linien), and KMail reduces false-positive scam warnings. Other updates include translatable settings in KDE Connect, a missing SVG file type fix in Kdenlive, and minor UI and stability fixes in apps like Okular, NeoChat and KWalletManager.

KDE Frameworks 6.20.0: The latest frameworks improves handling of vCard 4 properties like photos and death dates in KContacts, and has better trash detection for network filesystems in KIO. Key fixes include enhanced security in KWallet with modern session management, reduced crashes in image format plugins (KImageFormats) when handling malformed files, and improved User Interface consistency in Kirigami for overlays and action toolbars. The release also aligns with Qt 6.8+ by removing outdated version checks and improving CMake module policies across Extra CMake Modules.

Pillow 12.0.0: This major version modernizes Python image handling with better performance, cleaner APIs, and updated codec support, improving reliability for everyday image processing and development workflows. Users benefit from refreshed image libraries like libjpeg-turbo, libpng, FreeType, and WebP, which improves format support and rendering quality. Developers gain stricter type hints, improved testing, and new features like ImageText and enhanced TIFF handling. Support for Python 3.9 and very old FreeType versions is dropped, so older environments may need upgrading, but in return people get a faster, better-maintained imaging stack.

GNOME 49.2: This update provides noticeably fewer freezes, smoother window behavior, and more reliable lock-screen notifications, networking indicators, and keyboard input. Display calibration, offline updates, and the on-screen keyboard are also more dependable. GDM 49.2, GNOME Control Center 49.2.1, and gnome-session 49.2 all updated in the latter half of the month. Autologin now correctly falls back to X11 if Wayland fails, avoiding painful lockouts, while the Control Center no longer crashes when configuring global shortcuts. Apps like Calculator, Builder, and Boxes did clean up some long-standing bugs that affected everyday workflows.

Orca 49.5: Screen reading became clearer and less frustrating for everyday browsing and typing with this update. Users should notice less repeated speech on web pages, fewer verbose announcements, and more natural handling of editable tables in apps and websites. Typing passwords is also improved with spaces now spoken correctly instead of being silently ignored.

switcheroo-control 3.0: This major version update improves how hybrid-GPU laptops detect and switch between integrated and discrete graphics, which directly affects gaming performance, battery life, and desktop smoothness. The new API can now reliably discover discrete GPUs across AMD, Intel, NVIDIA, and Nouveau drivers, reducing cases where apps fail to pick the right GPU. Vulkan handling is cleaner thanks to support for driver selection through VK_LOADER_DRIVERS_SELECT, making GPU-intensive tools more predictable.

GStreamer 1.26.8: This update corrects colors when subtitles are enabled, has fewer glitches with oddly sized or subsampled video, and has smoother muxing and RTP handling in streaming or conferencing apps. Developers benefit from faster pad forwarding, better parsing for AAC and AV1, improved WebRTC deadlock avoidance, and clearer error messages.

PipeWire 1.5.83: Users should notice fewer sync issues with this release, more reliable Bluetooth/HDMI device changes. There is also improved streaming especially for RTP-based tools and apps using echo cancellation. Developers gain clearer format-parsing errors, more flexible multichannel support, and safer renegotiation behavior in GStreamer and SPA components. Despite being a release candidate, it keeps full ABI compatibility. Additional fixes reduce glitches across pro-audio, gaming, and desktop setups.

Key Package Updates

Kernel Source 6.17.9: This update provides AMD and Intel GPU fixes for suspend failures, display quirks and performance issues. Storage and filesystems (NFS, SMB, exFAT, EROFS) gain reliability improvements that reduce stalls and corruption risks. Networking and input devices receive targeted bug fixes for Wi-Fi, Ethernet, and HID peripherals. Futex and input–output memory management unit (IOMMU) updates improve memory handling and virtualization edge cases.

OpenSSH 10.2p1: This update improves connection reliability and strengthens future-proof security for anyone using SSH daily. Sessions are now more stable thanks to fixes for ControlPersist terminal issues, and key handling with agents or PKCS#11 tokens work more consistently. You’ll also see smarter QoS behavior: interactive sessions get better responsiveness while file transfers fall back to normal network priority. OpenSSH also begins phasing out weak SHA1 SSHFP records and warns when non–post-quantum algorithms are used, nudging users toward safer defaults without breaking current setups.

libvirt 11.9.0: This release improves GPU-like clarity for Hyper-V thanks to a new host-model mode that exposes exactly which enlightenments are active, and network interfaces can finally be hot-plugged on Cloud Hypervisor guests. USB controller selection is smarter and more consistent across architectures, while NVMe disks and virtio memory models gain cleaner, safer options.

Mesa 25.3.0 and 25.2.7: The 25.3.0 release adds OpenGL 4.6 and Vulkan 1.4 API support (depending on driver) along with extensions for video encode, atomic operations, robust context handling and shader features on various drivers. Many driver bugs and game-specific crashes have been fixed. Games like Borderlands 4, RE4 Separate Ways, No Man’s Sky, Endless Legend 2, and Penumbra: Overture see stability and rendering improvements version 25.2.7. Video encoding paths, uniform updates, and AV1 handling are also more reliable. Developers benefit from safer Vulkan and OpenGL state handling, corrected modifiers, and cleanup across ACO, RADV, PanVK, and llvmpipe. While no new features land, this update delivers a noticeably smoother and more predictable GPU experience.

curl 8.17.0: This update closes several vulnerabilities, including an SFTP host-verification flaw and a Windows path-traversal issue, making network transfers safer by default. Users and developers also benefit from more reliable TLS handling, fewer memory leaks, better socket management, and improved QUIC and HTTP/3 stability.

sdbootutil 1+git20251111.611edd1: This update smooths out system boot management, so day-to-day usage becomes a bit more predictable with cleaner configuration files, corrected package summaries, and fewer rpmlint-related quirks that could cause confusion or misbehavior in tooling. The release also improves compatibility by recognizing tracing parameters and adds a Snapper drop-in to support CAP_SYS_CHROOT, making snapshot-based recovery more robust.

coreutils 9.9: This update addresses performance regressions in cp and tail giving smoother handling of compressed or large files, while cksum and basenc regain correct behavior for modern formats. Developers and power users benefit from safer parsing in numfmt, more predictable error handling, and faster wc -l on AVX512 systems. A few edge cases, like Ceph snapshot directories or malformed compressor scripts, now behave more consistently.

fwupd 2.0.17: This update provides fewer failed updates, smoother activation for docks and devices, and better support for newer hardware like Framework’s Copilot keyboard and additional NVMe SSDs. Behind the scenes, fwupd adds post-quantum signature support, phased update deployment, cleaner cache handling, improved EFI parsing, and fixes several crashes involving Intel GPUs, docks, and nested firmware images.

crypto-policies 20250714.cd6043a: This cryptographic algorithm for your system provides stronger defaults with expanded post-quantum and hybrid crypto support, cleaner FIPS behavior, and fewer mismatches between tools. Developers benefit from clearer policy mappings, stricter cipher enabling, and improved test coverage across PQC-capable stacks.

Security Updates

curl 8.17.0:

OpenSMTPD:

  • CVE-2025-62875: Fixes a vulnerability that could trigger a shutdown and cause a denial of service.

Kernel Source 6.17.7:

  • CVE-2025-40013: Fixes a kernel NULL-pointer dereference issue in the Qualcomm ASoC audioreach driver that could lead to a crash.
  • CVE-2025-40028: Addresses a bug in the binder subsystem that could corrupt memory and cause a denial of service.
  • CVE-2025-40027: Fixes an issue in the filesystem that could cause unexpected kernel behavior.
  • CVE-2025-40026: Resolves a KVM x86 intercept-checking flaw that could allow incorrect guest/host handling.
  • CVE-2025-40025: Fixes missing sanity checks preventing filesystem corruption.
  • CVE-2025-40082: Fixes a slab out-of-bounds read in the hfsplus filesystem, preventing potential crashes.
  • CVE-2025-40081: Prevents integer overflows that could cause incorrect memory access.
  • CVE-2025-40080: Restricts NBD socket use to TCP/UDP to avoid unsafe socket operations.
  • CVE-2025-40079: Fixes incorrect sign extension handling in RISC-V return values.
  • CVE-2025-40078: Adds strict bounds checking reads to avoid invalid memory access.
  • CVE-2025-40077: Fixes a left-shift overflow problem.
  • CVE-2025-40076: Ensures PCI R-Car host uses the correct IRQ domain, avoiding interrupt misrouting.
  • CVE-2025-40075: Fixes incorrect network metric lookups.
  • CVE-2025-40074: Ensures IPv4 routing uses dst_dev_rcu correctly.
  • CVE-2025-40073: Prevents invalid SSPP validation in drm-msm when the hardware block is not required.
  • CVE-2025-40072: Adds proper return-value validation with mount namespace lookups.
  • CVE-2025-40071: Fixes input queue blocking that could lead to stalled data processing.
  • CVE-2025-40070: Fixes a warning and incorrect registration behavior.
  • CVE-2025-40069: Resolves an object leak in drm-msm during VM_BIND error handling.
  • CVE-2025-40068: Fixes an integer overflow preventing corrupted memory use.
  • CVE-2025-40067: Ensures NTFS3 rejects invalid index allocation when BITMAP data is inconsistent.
  • CVE-2025-40066: Adds required PHY checks during mt7996 WiFi initialization to prevent invalid operations.
  • CVE-2025-40065: Fixes incorrect HGATP writes in RISC-V KVM to ensure valid mode settings.
  • CVE-2025-40064: Fixes networking code during device namespace lookup.
  • CVE-2025-40063: Ensures consistent allocation in crypto compression code to prevent misuse.
  • CVE-2025-40062: Fixes a NULL pointer assignment.
  • CVE-2025-40061: Fixes a race condition that could lead to crashes.
  • CVE-2025-40060: Ensures proper NULL returns when allocations fail.
  • CVE-2025-40059: Fixes incorrect return-value handling in Coresight drivers.
  • CVE-2025-40018: Prevents premature FTP helper unregistering in IPVS during namespace teardown.
  • CVE-2025-40058: Blocks dirty-tracking setup on VT-d hardware that does not support coherent DMA.
  • CVE-2025-40057: Adds an upper bound for max_vclocks in PTP to avoid overflow or misuse.
  • CVE-2025-40056: Fixes incorrect return-value checks in vhost-vringh’s copy_to_iter path that could trigger data corruption.

Unbound 1.24.2:

  • CVE-2025-11411: Fixes for a vulnerability and potential DNS cache poisoning or domain hijacking.

X.Org Server 21.1.21:

  • CVE-2022-49737: Fixes a race condition that could lead to crashes or unintended behavior.
  • CVE-2025-26594: Fixes an issue that may access freed memory and lead to crashes or a code-execution risk.
  • CVE-2025-26595: Addresses a buffer-overflow risking memory corruption or crashes.
  • CVE-2025-26596: Fixes a heap-overflow that may cause memory corruption and potentially lead to crashes or exploitation.
  • CVE-2025-26597: Addresses a buffer-overflow risking memory corruption or denial of service.
  • CVE-2025-26598: Addresses an out-of-bounds write vulnerability that may overwrite memory, risk instability or exploitation.
  • CVE-2025-26599: Addresses a vulnerability that may cause crashes or unpredictable behavior.
  • CVE-2025-26600: Addresses a vulnerability leading to potential memory corruption or denial of service.
  • CVE-2025-26601: Fixes invalid memory access or unstable server behavior.
  • CVE-2025-49175: Fixes a vulnerability that could result in a server crash or cause resource misuse.
  • CVE-2025-49176: Addresses a flaw concerning a potential crash risk or potential exploitation.
  • CVE-2025-49177: Fixes a flaw that may result in invalid pointer dereferences or server instability.
  • CVE-2025-49178: Fixes a vulnerability that could trigger invalid memory access or denial of service.
  • CVE-2025-49179: Addresses a flaw concerning a buffer-overflow that had a potential crash risk or memory corruption.
  • CVE-2025-49180: Fixes a memory-handling bug that may cause invalid memory accesses or server crashes.
  • CVE-2025-62229: Addresses a crash or destabilize the display server.
  • CVE-2025-62230: Addresses a vulnerability that could invalidate memory access or denial of service when clients unregister resources.
  • CVE-2025-62231: Fixes a value-overflow bug that could have lead to an integer overflow.

grub2:

  • CVE-2025-54771: Addresses a memory corruption or a bootloader crash.
  • CVE-2025-54770: Addresses an issue that may trigger a potentially crashing the loader.
  • CVE-2025-61662: Fixes a manipulation that may crash or destabilize the boot process.
  • CVE-2025-61663: Fixes an issue that risks memory corruption or boot failures.
  • CVE-2025-61664: Addresses a possible loader instability or denial of service.
  • CVE-2025-61661: Addresses a vulnerability that could allow crafted USB hardware to corrupt memory, possibly enabling arbitrary code execution or boot compromise.

openexr 3.4.3:

  • CVE-2025-64181: Fixes a problem could lead to crashes or memory corruption when processing specially crafted .exr files.
  • CVE-2025-64182: A vulnerability may allow out-of-bounds behavior and potential code execution.
  • CVE-2025-64183: An issue that affects safety when loading certain images, leading to potential memory safety problems.

**python313 **:

  • CVE-2025-6075: Fixes a weakness causing high CPU use or performance degradation.
  • CVE-2025-8291: Addresses specially crafted ZIP files that may be parsed incorrectly, potentially breaking archive integrity or causing unexpected behavior.

Xen 4.20.1_08:

  • CVE-2025-58149: A fix for a hypervisor flaw that could have let a guest access memory.

python-Brotli 1.2.0:

  • CVE-2025-6176: A fix for a flaw that could cause a remote server denial of service.

Mozilla Firefox 145.0:

  • CVE-2025-13021: A boundary-checking flaw could allow remote code execution by a malicious web page.
  • CVE-2025-13022: Another boundary-condition bug that enables sandbox escape or arbitrary code execution.
  • CVE-2025-13012: A race-condition vulnerability that may lead to data corruption or memory compromise when exploited.
  • CVE-2025-13023: A sandbox-escape issue allowing an attacker to break out of the browser sandbox.

Users are advised to update to the latest versions to mitigate these vulnerabilities.

Conclusion

Tumbleweed in November a steady cadence of updates that balanced desktop refinement with core system resilience. Plasma 6.5.3, KDE Gear 25.08.3 and GNOME 49.2 sharpened daily usability, while kernel 6.17.9, Mesa 25.3.0 and PipeWire 1.5.83 strengthened performance across graphics, audio and hardware support. Security remained front-and-center with fixes spanning the kernel, bootloader, network stack, browsers and virtualization.

Slowroll Arrivals

Please note that these updates also apply to Slowroll and arrive between an average of 5 to 10 days after being released in Tumbleweed snapshot. This monthly approach has been consistent for many months, ensuring stability and timely enhancements for users. Updated packages for Slowroll are regularly published in emails on openSUSE Factory mailing list.

Contributing to openSUSE Tumbleweed

Stay updated with the latest snapshots by subscribing to the openSUSE Factory mailing list. For those Tumbleweed users who want to contribute or want to engage with detailed technological discussions, subscribe to the openSUSE Factory mailing list . The openSUSE team encourages users to continue participating through bug reports, feature suggestions and discussions.

Your contributions and feedback make openSUSE Tumbleweed better with every update. Whether reporting bugs, suggesting features, or participating in community discussions, your involvement is highly valued.

the avatar of Zoltán Balogh

I want to have a hot shower

It all started last summer

When my family moved to a new place. In our previous home we had a district heating service that included unlimited hot water for a fixed price. That was awesome - not very environmentally friendly and actually not very cheap, but we never ran out of hot water.

The boiler

In our new home we are independent from the city’s hot water services. This is good because we pay exactly for the energy we use. It means that we have a 300-liter hot water heater that we turn on when we want to make as much hot water as we need. In most households such a hot water boiler has a thermostat set to a specific temperature and the heater keeps all 300 liters of water as hot as it is set. I do not like this, because regardless of how great the insulation on the water tank is, it loses temperature over time. I needed a smarter system.

the avatar of SUSE Community Blog

the avatar of openSUSE News

Planet News Roundup

This is a roundup of articles from the openSUSE community listed on planet.opensuse.org.

The below featured highlights listed on the community’s blog feed aggregator are from November 22 to 28.

Blog posts this week highlight a broad mix of desktop improvements, community efforts, and privacy awareness. KDE Plasma sees notable progress in accessibility and KDE also launches its 2025 fundraising campaign while some prepare for a major open-source seminar. Elsewhere, there’s hands-on Linux hardware coverage with Intel NPU drivers, packaging guidance for RPM maintainers, an openSUSE Hack Week aiming to improve membership workflows, and sharp commentary on user privacy as well as concerns about Smart TV terms-of-service.

Here is a summary and links for each post:

Most of the access to Plasma 6.5

KDE Blog outlines accessibility improvements in Plasma 6.5 aimed at making the desktop more usable for visually or hearing-impaired users. Screen readers like Orca can now announce Caps Lock status and better describe keyboard shortcuts. Additional enhancements include flicker-free rendering to reduce photosensitivity risk, improved overall keyboard navigation across Plasma and more.

rpm premable – order matters

Nordisch explains a build issue encountered when packaging PostgreSQL extensions: macros like %{version} and %{release} remained unexpanded because they were defined after references to them in the preamble. The post serves as a reminder to maintain a consistent spec-file header order to avoid subtle build errors.

Help us reach the tipping point!: Fundraising campaign for KDE 2025

The KDE Blog calls for donations to support the 2025 fundraising drive under the slogan “Help us reach the inflection point,” stressing that much of KDE’s funding comes from private supporters. The funds will help maintain servers, support developer sprints and events like conferences. Users are invited to “adopt” a KDE application by donating and publicly showing their support.

Hack Week Project Takes Aim at Improving Membership Management

The post announces a Hack Week 25 project called openSUSE Lounge, which is a new platform aiming to centralize and simplify membership management for openSUSE. openSUSE Lounge aims to maintain member records, track membership status, support election tasks, and ease the workload for membership and election officials.

Black Friday 2025 de Slimbook

The KDE Blog announces real Black Friday discounts on Slimbook laptops and desktops. Saving range from ~ €30 to €150 depending on the model. The post also invites the community to join the #KDEslimbook social campaign and to show off their Plasma setups to win merchandise and celebrate Linux-ready hardware.

Installing Intel NPU Driver on Linux

The blog explains how to install the Intel NPU Driver on Linux while enabling support for the NPU (neural processing unit) present in modern Intel Core Ultra CPUs. The post outlines that the driver stack consists of a kernel module (intel_vpu) and a user-space stack including a compiler, Level Zero runtime and firmware.

Victorhck reports that GrapheneOS has decided to move all its website, forum and social-media servers from France to foreign hosts due to legal pressure, which appear to be hostile toward open-source privacy projects. Hosting will shift from the French provider OVHCloud to a mix of servers in Toronto and Germany.

KDE Express Episode 58: Building Community with Paco Estrada

This episode of KDE Express welcomes back podcaster Paco Estrada to discuss his return to producing regular episodes about GNU/Linux and free-software. The conversation reviews his plans for 2026 and reflects on the role of community podcasts in the free-software ecosystem.

I read the terms of service for my Smart TV and now I sleep with one eye open

Victorhck recounts reading the “terms of service” for his new Smart TV and realizes its written as a consent to constant surveillance. The clauses grant the manufacturer rights to record video, listen to audio, collect usage data, push mandatory firmware updates, and even treat the TV as licensed (not sold), undermining user autonomy.

KDE will be present at the 4th Annual Opensource Seminar

The KDE Blog announces that the community will participate in the “IV Seminario Anual Opensource”, which is an online event covering GNU/Linux, system administration, server setups, and security topics. The event is Nov. 29 at 21:00 CET.

User interface and performance improvements – This week in Plasma

KDE’s weekly update reports a batch of UI and performance improvements in KDE Plasma aimed for the upcoming 6.6.0 release. Users can now choose to exclude specific windows from screen recordings, blur effects in dark mode are more refined (and can have customizable saturation), and task-switching order when using grouped icons now respects most-recent use rather than always prioritizing full-screen windows.

View more blogs or learn to publish your own on planet.opensuse.org.

a silhouette of a person's head and shoulders, used as a default avatar

Tumbleweed – Review of the weeks 2025/47 & 48

Dear Tumbleweed users and hackers,

The last two weeks have been quite steady for Tumbleweed: solid 10 snapshots could be built, tested, and released (0513…0526)

The most relevant changes from those two weeks are:

  • GStreamer 1.26.8
  • Pipewire 1.5.83
  • Mesa 25.2.7 & 25.3.0
  • Mozilla Firefox 145.0
  • btrfsprogs 6.17.1
  • KDE Frameworks 6.20.0
  • fwupd 2.0.17
  • XEN 4.20.2 & 4.21.0
  • Linux kernel 6.17.8 & 6.17.9: enabled efidrm and vesadrm
  • KDE Plasma 6.5.3
  • cURL 8.17.0
  • Freetype 2.14.1
  • Samba 4.22.6
  • GNOME 49.2
  • gpg 2.5.14
  • Qt 6.10.1

Our staging areas are busy testing these changes:

  • Systemd 258.2
  • openSSL 3.6.0
  • Ruby 4.0 (pre-release, testing early)

Week 2025/49 will be hackweek! https://hackweek.opensuse.org/ Feel free to join in, find a project to participate or even work on your own project. There can only be winners!

a silhouette of a person's head and shoulders, used as a default avatar
a silhouette of a person's head and shoulders, used as a default avatar
darix posted at

rpm premable - order matters

The other day while working on pgrx based postgresql extensions, I saw a weird errors in the build log.

warning: line 29: Possible unexpanded macro in: Provides:       postgresql18-someextension-llvmjit = %{version}-%{release}
warning: line 29: Possible unexpanded macro in: Obsoletes:      postgresql18-someextension-llvmjit < %{version}-%{release}

This is odd. The Version and Release are set. So what is going on here:

%if "%{pg_name}" == ""
Name:           %{ext_name}
ExclusiveArch:  do_not_build
%else
Name:           %{pg_name}-%{ext_name}
BuildRequires:  %{pg_name}-pgrx
%pg_server_requires
%endif
Version:        1.0.0
Release:        0

The warning comes from %pg_server_requires, which then calls %pg_obsolete_llvm_subpackage. This preamble block was a slight deviation from the pattern I was usually following. I made the change because I saw “wait I can group up some stuff”

the avatar of openSUSE News

Hack Week Project Takes Aim at Improving Membership Management

A Hack Week 25 project is looking to simplify how the openSUSE community manages memberships through a new platform called openSUSE Lounge.

The openSUSE Lounge project proposes a centralized system for maintaining member records, tracking membership status and supporting election-related tasks, all while reducing the manual workload placed on membership and election officials.

The platform is designed to give Member Officials a clearer, more efficient way to keep the member database accurate. Election officials could use the tool to export up-to-date voter lists, detect issues such as bounced credential emails and flag outdated or inactive accounts earlier in the process.

Longer-term plans may include allowing contributors to apply for membership directly through the interface, which could streamline onboarding and increase transparency for those seeking membership.

The prototype currently uses a Laravel backend paired with Tailwind CSS and Alpine.js for a lightweight interface. MariaDB powers the underlying data layer. A preview of the user interface was shared with the project through a pull request. More functionality is planned as Hack Week continues.

openlounge

The project could provide a step toward modernizing membership management for the project and improve how the community maintains this data.

Hack Week, which began in 2007, has become a cornerstone of the project’s open-source culture. Hack Week has produced tools that are now integral to the openSUSE ecosystem, such as openQA, Weblate and Aeon Desktop. Hack Week has also seeded projects that later grew into widely used products; the origins of ownCloud and its fork Nextcloud derive from a Hack Week project started more than a decade ago.

For more information, visit hackweek.opensuse.org.

a silhouette of a person's head and shoulders, used as a default avatar

Rescuing most from a broken tar.bz2 with bzip2recover and some cunning.

I had a bzip2ed tarball from 2005 lying around, for which BZip2 threw a CRC error.
libv@machine:~$ tar -jxvf ../backup-2005.tar.bz2 
backup/
backup/file0.txt
backup/file1.pdf
backup/file2.bin

bzip2: Data integrity error when decompressing.
 Input file = (stdin), output file = (stdout)

It is possible that the compressed file(s) have become corrupted.
You can use the -tvv option to test integrity of such files.

You can use the `bzip2recover' program to attempt to recover
data from undamaged sections of corrupted files.

tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
I then ran bzip2recover, and this produced 328 files called:
rec00001backup-2005.tar.bz2
rec00002backup-2005.tar.bz2
..
rec00327backup-2005.tar.bz2
rec00328backup-2005.tar.bz2
There is surprisingly little information out there on how to handle this. One stackoverflow commenter stated to "guess" the size of the undecompressable block, which sounds a bit unscientific.

So the next step was to run bunzip2 on all of them, which broke with:
bunzip2: Data integrity error when decompressing.
 Input file = rec00051backup-2005.tar.bz2, output file = rec00051backup-2005.tar

It is possible that the compressed file(s) have become corrupted.
You can use the -tvv option to test integrity of such files.

You can use the `bzip2recover' program to attempt to recover
data from undamaged sections of corrupted files.

bunzip2: Deleting output file rec00051backup-2005.tar, if it exists.
bunzip2: WARNING: some files have not been processed:
bunzip2:    328 specified on command line, 277 not processed yet.
There does not seem to be a flag for bunzip2 to ignore the CRC and soldier on, flagging the block accordingly. This 900kB block should be considered lost. The rest of the data is still valid though. So we need to trick tar into thinking that there is valid data in where the breakage was. Sadly Bzip2 does not list the actual uncompressed block size, just an approximation (in this case a "9" for 900kB).

I then bunzipped all the other files, and catted the first good .tar files together as one file, and the last good tar files together as another.

So i quickly read up on the tar header format. It's 512byte aligned, with the first 256bytes the name of the file or directory, null padded. Then all of the other relevant information is presented in the next 256 bytes:
00000000  62 61 63 6b 75 70 2f 00  00 00 00 00 00 00 00 00  |backup/.........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000060  00 00 00 00 30 30 30 30  37 35 35 00 30 30 30 30  |....0000755.0000|
00000070  30 30 30 00 30 30 30 30  30 30 30 00 30 30 30 30  |000.0000000.0000|
00000080  30 30 30 30 30 30 30 00  31 30 30 32 37 31 37 35  |0000000.10027175|
00000090  33 35 34 00 30 31 32 31  33 30 00 20 35 00 00 00  |354.012130. 5...|
000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000100  00 75 73 74 61 72 20 20  00 6c 69 62 76 00 00 00  |.ustar  .libv...|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 00 00  00 6c 69 62 76 00 00 00  |.........libv...|
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000140  00 00 00 00 00 00 00 00  00 30 30 30 30 30 30 30  |.........0000000|
00000150  00 30 30 30 30 30 30 30  00 00 00 00 00 00 00 00  |.0000000........|
00000160  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  62 61 63 6b 75 70 2f 66  69 6c 65 30 2e 74 78 74  |backup/file0.txt|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000220  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000260  00 00 00 00 30 30 30 30  37 35 35 00 30 30 30 30  |....0000755.0000|
00000270  30 30 30 00 30 30 30 30  30 30 30 00 30 30 30 31  |000.0000000.0001|
00000280  35 36 37 31 30 30 30 00  31 30 32 34 32 31 30 31  |5671000.10242101|
00000290  30 34 30 00 30 31 35 30  37 35 00 20 30 00 00 00  |040.015075. 0...|
000002a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000300  00 75 73 74 61 72 20 20  00 6c 69 62 76 00 00 00  |.ustar  .libv...|
00000310  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  00 6c 69 62 76 00 00 00  |.........libv...|
00000330  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000340  00 00 00 00 00 00 00 00  00 30 30 30 30 30 30 30  |.........0000000|
00000350  00 30 30 30 30 30 30 30  00 00 00 00 00 00 00 00  |.0000000........|
00000360  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  54 68 69 73 20 69 73 20  79 6f 75 72 20 64 61 74  |This is your dat|
You can see here that the string "00015671000" at 0x27C is the file size that tar expects for file0.txt. This is octal, so you need to run:
echo $((8#00015671000))
36336643633664
While there is no tar specific magic, i was able to search the hexdump for "ustar".

I then found that i got lucky, and that a big file was spanning the broken block. Its tar header was at 0x607800 in the first blob:
00607800  62 61 63 6b 75 70 2f 66  69 6c 65 32 2e 62 69 6e  |backup/file2.bin|
00607810  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00607860  00 00 00 00 30 30 30 30  37 35 35 00 30 30 30 30  |....0000755.0000|
00607870  30 30 30 00 30 30 30 30  30 30 30 00 30 31 30 34  |000.0000000.0104|
00607880  34 32 36 34 30 30 30 00  31 30 32 34 30 32 31 37  |4264000.10240217|
00607890  35 33 34 00 30 32 30 35  30 32 00 20 30 00 00 00  |534.020502. 0...|
006078a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00607900  00 75 73 74 61 72 20 20  00 6c 69 62 76 00 00 00  |.ustar  .libv...|
00607910  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00607920  00 00 00 00 00 00 00 00  00 6c 69 62 76 00 00 00  |.........libv...|
00607930  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00607940  00 00 00 00 00 00 00 00  00 30 30 30 30 30 30 30  |.........0000000|
00607950  00 30 30 30 30 30 30 30  00 00 00 00 00 00 00 00  |.0000000........|
00607960  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00607a00  64 61 74 61 64 61 74 61  64 61 74 61 64 61 74 61  |datadatadatadata|
Because this is the first block, before the corruption, everything is still nicely 0x200 aligned. Our file begins at 0x607a00 with a filesize of 0x8916800 (or 1044264000 octal -- which is surprisingly 0x200 aligned as well -- is this a filesystem thing?). The first blob's size is 0x2af3b17. So the missing amount of data for this file is
(0x607a00 + 0x8916800) - 0x2af3b17 = 0x642A6E9
The second blob was slightly more difficult, as there the tar header is no longer 0x200 aligned. I got unlucky with searching the hexdump for "ustar" as it crossed a 16byte boundary, but grep gave me a byteoffset to look for in the hexdump.
0634eb50  00 00 00 00 00 00 00 00  00 00 00 00 62 61 63 6b  |............back|
0634eb60  75 70 2f 66 69 6c 65 33  2e 73 68 00 00 00 00 00  |up/file3.sh.....|
0634eb70  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
I then of course made the error of using 0x634eb50 and not 0x634eb5c in my calculation. But on the second attempt i calculated:
0x642A6E9 - 0x634eb5c = 0xDBB8D
So i dded the required amount to some file, catted the three files together, and tar was perfectly happy. I did null the broken file, and renamed it appropriately.

It is not likely that i will need this again any time soon, but if i do, i hope i know where to find the info now.

a silhouette of a person's head and shoulders, used as a default avatar
a silhouette of a person's head and shoulders, used as a default avatar
darix posted at

Zypp - different and still the same

zypp makes sure that it not just randomly moves between repositories of different vendors. Vendors in this case can be the (open)SUSE base packages and different buildservice repositories. If you want to do it via

zypper dup --from <repoid>

You get a lot of questions for “do you really want to change the vendor?”. When you do that e.g. to test the next GNOME major release from GNOME:Next, that is a lot of questions. Like a few hundred times. My manual way involved putting 1\n into the mouse cut buffer and pasting with my middle mouse button.