From 10fef35fe641af87f47f3d7befc7996cc8835bce Mon Sep 17 00:00:00 2001 From: Mex <44814932+MMexicann@users.noreply.github.com> Date: Sat, 14 Nov 2026 21:35:21 +0100 Subject: [PATCH 1/3] M1: reject leading-zero numeric prerelease versions --- xtask/src/version.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/xtask/src/version.rs b/xtask/src/version.rs index 8c4c1fc34..7675edad6 100644 --- a/xtask/src/version.rs +++ b/xtask/src/version.rs @@ -49,7 +49,12 @@ pub fn validate(v: &str) -> Result<(), String> { return bad(); } if let Some(p) = pre - && (p.is_empty() || p.split('.').any(|id| id.is_empty() || !id.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-'))) + && (p.is_empty() + || p.split('.').any(|id| { + id.is_empty() + || !id.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-') + || (id.len() > 1 && id.starts_with('0') && id.bytes().all(|b| b.is_ascii_digit())) + })) { return bad(); } @@ -144,6 +149,18 @@ mod tests { assert!(replace(MANIFEST, "nope").is_err()); } + #[test] + fn numeric_prerelease_identifiers_have_no_leading_zeroes() { + for bad in ["1.0.0-00", "1.0.0-01", "1.0.0-rc.01"] { + assert!(validate(bad).is_err(), "{bad}"); + assert!(replace(MANIFEST, bad).is_err(), "{bad} must not reach the manifest"); + } + for ok in ["1.0.0-0", "1.0.0-rc.0", "1.0.0-01a", "1.0.0-0-1"] { + assert!(validate(ok).is_ok(), "{ok}"); + assert_eq!(read(&replace(MANIFEST, ok).unwrap()).unwrap(), ok); + } + } + #[test] fn the_real_manifest_has_a_valid_version() { let text = std::fs::read_to_string(crate::root().join("Cargo.toml")).unwrap(); From 3c604486917d40e4abc00d1f6e471fab4a5deca4 Mon Sep 17 00:00:00 2001 From: "autocraft-bot[bot]" <354215646+autocraft-bot[bot]@users.noreply.github.com> Date: Sun, 15 Nov 2026 03:20:15 +0000 Subject: [PATCH 2/3] Apply review fixes - xtask/src/version.rs --- xtask/src/version.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xtask/src/version.rs b/xtask/src/version.rs index 7675edad6..795070577 100644 --- a/xtask/src/version.rs +++ b/xtask/src/version.rs @@ -45,7 +45,11 @@ pub fn validate(v: &str) -> Result<(), String> { None => (v, None), }; let nums: Vec<&str> = core.split('.').collect(); - if nums.len() != 3 || nums.iter().any(|n| n.is_empty() || !n.bytes().all(|b| b.is_ascii_digit()) || (n.len() > 1 && n.starts_with('0'))) { + if nums.len() != 3 + || nums + .iter() + .any(|n| n.is_empty() || !n.bytes().all(|b| b.is_ascii_digit()) || n.parse::().is_err() || (n.len() > 1 && n.starts_with('0'))) + { return bad(); } if let Some(p) = pre From 04907481c14b2e1c45e9d2e28da008b9659ffb3b Mon Sep 17 00:00:00 2001 From: "autocraft-bot[bot]" <354215646+autocraft-bot[bot]@users.noreply.github.com> Date: Sun, 15 Nov 2026 03:43:10 +0000 Subject: [PATCH 3/3] Apply review fixes - xtask/src/version.rs --- xtask/src/version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtask/src/version.rs b/xtask/src/version.rs index 795070577..50fb8f040 100644 --- a/xtask/src/version.rs +++ b/xtask/src/version.rs @@ -147,7 +147,7 @@ mod tests { for ok in ["0.1.0", "1.20.300", "1.0.0-rc.1", "1.0.0-alpha", "1.0.0-x-y.2"] { assert!(validate(ok).is_ok(), "{ok}"); } - for bad in ["1.0", "1.0.0.0", "v1.0.0", "01.0.0", "1.0.0-", "1.0.0-a..b", "1.0.0+meta", "1.a.0", ""] { + for bad in ["1.0", "1.0.0.0", "v1.0.0", "01.0.0", "1.0.0-", "1.0.0-a..b", "1.0.0+meta", "1.a.0", "18446744073709551616.0.0", ""] { assert!(validate(bad).is_err(), "{bad}"); } assert!(replace(MANIFEST, "nope").is_err());