From: Stoiko Ivanov <s.ivanov@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer 2/2] common: pinning: use pve-iface regular expression for validation
Date: Wed, 26 Nov 2025 19:07:16 +0100 [thread overview]
Message-ID: <20251126180819.817240-3-s.ivanov@proxmox.com> (raw)
In-Reply-To: <20251126180819.817240-1-s.ivanov@proxmox.com>
the previous attempts at mimicking the `pve-iface` validation in
pve-common mis-read the validation, or missed some corner-cases.
So instead of trying to rebuild a regex validation, simply copy the
regular expression from pve-common. Following the recommendation at
https://docs.rs/regex/latest/regex/#overview by using RegexBuilder for
case-insensitive matching.
I kept the length-check at {1,20}, to have this as close to the
original as possible, as we restrict the length to 15 in the checks
before anyways.
Fixes: 47700a5 ("common: pinning: require first character to be lower-case ascii")
Reported-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
proxmox-installer-common/src/options.rs | 51 +++++++++----------------
1 file changed, 18 insertions(+), 33 deletions(-)
diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs
index 34d0725..fbc0207 100644
--- a/proxmox-installer-common/src/options.rs
+++ b/proxmox-installer-common/src/options.rs
@@ -1,5 +1,5 @@
use anyhow::{Result, bail};
-use regex::Regex;
+use regex::{Regex, RegexBuilder};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::{IpAddr, Ipv4Addr};
@@ -517,25 +517,18 @@ impl NetworkInterfacePinningOptions {
);
}
- if name.chars().all(char::is_numeric) {
- bail!(
- "interface name '{name}' for '{mac}' is invalid: name must not be fully numeric"
- );
- }
-
// Mimicking the `pve-iface` schema verification
- if !name.starts_with(|c: char| c.is_ascii_lowercase()) {
- bail!(
- "interface name '{name}' for '{mac}' is invalid: name must start with a lowercase letter"
- );
- }
-
- if !name
- .chars()
- .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_')
- {
+ static RE: OnceLock<Regex> = OnceLock::new();
+ let re = RE.get_or_init(|| {
+ RegexBuilder::new(r"^[a-z][a-z0-9_]{1,20}([:\.]\d+)?$")
+ .case_insensitive(true)
+ .build()
+ .unwrap()
+ });
+
+ if !re.is_match(name) {
bail!(
- "interface name '{name}' for '{mac}' is invalid: name must only consist of alphanumeric lowercase characters and underscores"
+ "interface name '{name}' for '{mac}' is invalid: name must start with a letter and contain only ascii characters, digits and underscores"
);
}
@@ -1022,7 +1015,7 @@ mod tests {
assert!(res.is_err());
assert_eq!(
res.unwrap_err().to_string(),
- "interface name 'nic-' for 'ab:cd:ef:12:34:56' is invalid: name must only consist of alphanumeric lowercase characters and underscores"
+ "interface name 'nic-' for 'ab:cd:ef:12:34:56' is invalid: name must start with a letter and contain only ascii characters, digits and underscores"
)
}
@@ -1037,7 +1030,7 @@ mod tests {
assert!(res.is_err());
assert_eq!(
res.unwrap_err().to_string(),
- "interface name '0nic' for 'ab:cd:ef:12:34:56' is invalid: name must start with a lowercase letter"
+ "interface name '0nic' for 'ab:cd:ef:12:34:56' is invalid: name must start with a letter and contain only ascii characters, digits and underscores"
);
options
@@ -1048,34 +1041,26 @@ mod tests {
assert!(res.is_err());
assert_eq!(
res.unwrap_err().to_string(),
- "interface name '_a' for 'ab:cd:ef:12:34:56' is invalid: name must start with a lowercase letter"
+ "interface name '_a' for 'ab:cd:ef:12:34:56' is invalid: name must start with a letter and contain only ascii characters, digits and underscores"
);
}
#[test]
- fn network_interface_pinning_options_fail_on_uppercase_char() {
+ fn network_interface_pinning_options_pass_on_uppercase_char() {
let mut options = NetworkInterfacePinningOptions::default();
options
.mapping
.insert("ab:cd:ef:12:34:56".to_owned(), "Nic0".to_owned());
let res = options.verify();
- assert!(res.is_err());
- assert_eq!(
- res.unwrap_err().to_string(),
- "interface name 'Nic0' for 'ab:cd:ef:12:34:56' is invalid: name must start with a lowercase letter"
- );
+ assert!(res.is_ok());
options
.mapping
.insert("ab:cd:ef:12:34:56".to_owned(), "nIc0".to_owned());
let res = options.verify();
- assert!(res.is_err());
- assert_eq!(
- res.unwrap_err().to_string(),
- "interface name 'nIc0' for 'ab:cd:ef:12:34:56' is invalid: name must only consist of alphanumeric lowercase characters and underscores"
- );
+ assert!(res.is_ok());
options
.mapping
@@ -1096,7 +1081,7 @@ mod tests {
assert!(res.is_err());
assert_eq!(
res.unwrap_err().to_string(),
- "interface name '12345' for 'ab:cd:ef:12:34:56' is invalid: name must not be fully numeric"
+ "interface name '12345' for 'ab:cd:ef:12:34:56' is invalid: name must start with a letter and contain only ascii characters, digits and underscores"
)
}
}
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-11-26 18:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-26 18:07 [pve-devel] [PATCH installer 0/2] sync allowed nic-names with pve-common by using the same regex Stoiko Ivanov
2025-11-26 18:07 ` [pve-devel] [PATCH installer 1/2] sys: net: use literal pve-iface regular expression for validation Stoiko Ivanov
2025-11-26 18:07 ` Stoiko Ivanov [this message]
2025-11-27 7:18 ` [pve-devel] applied: [PATCH installer 0/2] sync allowed nic-names with pve-common by using the same regex Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251126180819.817240-3-s.ivanov@proxmox.com \
--to=s.ivanov@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.