cob: further restrict TypeName

Domain Names have restrictions on their total length, and the length
of individual labels[^0].

Since `TypeName`s are expected to be reverse domain name strings, the
total length of the internal string should not exceed 255 and each
component should not exceed 63.

[^0]: https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4
This commit is contained in:
Fintan Halpenny 2026-02-03 11:35:01 +00:00 committed by Lorenz Leutgeb
parent fe09cd4a00
commit 82ad52b169
2 changed files with 29 additions and 0 deletions

View File

@ -34,6 +34,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Callers should no longer expect the `fetching` inside that JSON result. Callers should no longer expect the `fetching` inside that JSON result.
- The `rad debug` information for ongoing fetches contained the number of - The `rad debug` information for ongoing fetches contained the number of
subscribers awaiting for results, this was removed. subscribers awaiting for results, this was removed.
- The `TypeName` strings defined in `radicle-cob` are restricted to reflect the
size limits on domain names as specified in
[RFC-1035](https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4).
## 1.6.1 ## 1.6.1

View File

@ -10,6 +10,9 @@ use thiserror::Error;
/// alphanumeric characters or hyphens separated by a period. Each /// alphanumeric characters or hyphens separated by a period. Each
/// component must start and end with an alphanumeric character. /// component must start and end with an alphanumeric character.
/// ///
/// The total length of a typename MUST NOT exceed 255, and each component
/// length MUST NOT exceed 63.
///
/// # Examples /// # Examples
/// ///
/// * `abc.def` /// * `abc.def`
@ -19,6 +22,9 @@ use thiserror::Error;
pub struct TypeName(String); pub struct TypeName(String);
impl TypeName { impl TypeName {
const MAX_LENGTH: usize = 255;
const MAX_COMPONENT: usize = 63;
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
&self.0 &self.0
} }
@ -40,8 +46,18 @@ impl FromStr for TypeName {
type Err = TypeNameParse; type Err = TypeNameParse;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() > Self::MAX_LENGTH {
return Err(TypeNameParse {
invalid: s.to_string(),
});
}
let split = s.split('.'); let split = s.split('.');
for component in split { for component in split {
if component.len() > Self::MAX_COMPONENT {
return Err(TypeNameParse {
invalid: s.to_string(),
});
}
if component.is_empty() { if component.is_empty() {
return Err(TypeNameParse { return Err(TypeNameParse {
invalid: s.to_string(), invalid: s.to_string(),
@ -100,5 +116,15 @@ mod test {
assert!(TypeName::from_str("abc..ghi").is_err()); assert!(TypeName::from_str("abc..ghi").is_err());
assert!(TypeName::from_str("abc.-123.ghi").is_err()); assert!(TypeName::from_str("abc.-123.ghi").is_err());
assert!(TypeName::from_str("abc.123-.ghi").is_err()); assert!(TypeName::from_str("abc.123-.ghi").is_err());
assert!(TypeName::from_str(&format!(
"a.very.long.name.that.exceeds.the.two-hundred-and-fifty-five.length.limit.{}",
"a".repeat(255)
))
.is_err());
assert!(TypeName::from_str(&format!(
"component.exceeds.sixty-three.limit.{}",
"a".repeat(64)
))
.is_err());
} }
} }