From 29e405f11fe0d1fb55b34ec10053cd02729cd1c4 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Sat, 26 Sep 2026 18:14:17 -0700 Subject: [PATCH] fix(bls): sort numeric version segments newer than letters When only one version had a digit at the current position, both sides were parsed as numbers and the letter side read as 0. "0" then compared equal to "a" and the result depended on what followed. Per the specification, the side with digits is newer. --- crates/bls/src/lib.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/bls/src/lib.rs b/crates/bls/src/lib.rs index ded2222..fec8346 100644 --- a/crates/bls/src/lib.rs +++ b/crates/bls/src/lib.rs @@ -294,9 +294,14 @@ pub fn compare_versions(a: &str, b: &str) -> Ordering { handle_single_char!(ca, cb, a_chars, b_chars, '.'); // Handle digits with numerical comparison. - // We key off of the A character being a digit intentionally as we presume - // this indicates it will be the same at this position. + // If only one string has digits at this position, that string is newer. if ca.is_ascii_digit() || cb.is_ascii_digit() { + if !ca.is_ascii_digit() { + return Ordering::Less; + } + if !cb.is_ascii_digit() { + return Ordering::Greater; + } let result = compare_numeric(&mut a_chars, &mut b_chars); if result != Ordering::Equal { return result; @@ -719,6 +724,14 @@ efi /EFI/fedora/shimx64.efi assert_eq!(compare_versions("", "1"), Ordering::Less); } + #[test] + fn digits_are_newer_than_letters() { + assert_eq!(compare_versions("0", "a"), Ordering::Greater); + assert_eq!(compare_versions("a", "0"), Ordering::Less); + assert_eq!(compare_versions("1.0", "1.a"), Ordering::Greater); + assert_eq!(compare_versions("1.a", "1.0"), Ordering::Less); + } + #[test] fn optional_both_none_equal() { assert_eq!(compare_versions_optional(None, None), Ordering::Equal);