Fail closed on unsupported Rust schema constructs
This commit is contained in:
parent
d0b745950b
commit
a61ba4d365
2 changed files with 366 additions and 11 deletions
|
|
@ -98,6 +98,46 @@ impl<'de, const MIN: usize, const MAX: usize> serde::Deserialize<'de> for Bounde
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct BoundedUrl<const MIN: usize, const MAX: usize>(url::Url);
|
||||
|
||||
impl<'de, const MIN: usize, const MAX: usize> serde::Deserialize<'de> for BoundedUrl<MIN, MAX> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let value = <String as serde::Deserialize>::deserialize(deserializer)?;
|
||||
if !(MIN..=MAX).contains(&value.chars().count()) {
|
||||
return Err(serde::de::Error::custom("URL length outside bounds"));
|
||||
}
|
||||
url::Url::parse(&value)
|
||||
.map(Self)
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct BoundedVec<T, const MIN: usize, const MAX: usize>(Vec<T>);
|
||||
|
||||
impl<'de, T, const MIN: usize, const MAX: usize> serde::Deserialize<'de> for BoundedVec<T, MIN, MAX>
|
||||
where
|
||||
T: serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let value = <Vec<T> as serde::Deserialize>::deserialize(deserializer)?;
|
||||
if (MIN..=MAX).contains(&value.len()) {
|
||||
Ok(Self(value))
|
||||
} else {
|
||||
Err(serde::de::Error::custom("array length outside bounds"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct OpaqueId(String);
|
||||
|
|
@ -212,7 +252,7 @@ pub struct TargetOverride {
|
|||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct HttpSourceSubmission {
|
||||
pub url: url::Url,
|
||||
pub url: BoundedUrl<0, 8192>,
|
||||
pub result_path: ResultPath,
|
||||
pub credential_id: Option<CredentialId>,
|
||||
}
|
||||
|
|
@ -231,8 +271,8 @@ pub struct ObjectStoreSourceSubmission {
|
|||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct HuggingFaceSelection {
|
||||
pub paths: Option<Vec<ResultPath>>,
|
||||
pub prefixes: Option<Vec<ResultPath>>,
|
||||
pub paths: Option<BoundedVec<ResultPath, 0, 10000>>,
|
||||
pub prefixes: Option<BoundedVec<ResultPath, 0, 10000>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
|
|
@ -324,9 +364,9 @@ pub struct EventProgress {
|
|||
pub attempt_id: OpaqueId,
|
||||
pub fence: BoundedU64<1, 9007199254740991>,
|
||||
pub completed_bytes: BoundedU64<0, 9007199254740991>,
|
||||
pub total_bytes: Option<Option<i64>>,
|
||||
pub total_bytes: Option<Option<BoundedU64<0, 9007199254740991>>>,
|
||||
pub completed_members: BoundedU64<0, 9007199254740991>,
|
||||
pub total_members: Option<Option<i64>>,
|
||||
pub total_members: Option<Option<BoundedU64<0, 9007199254740991>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
|
|
|
|||
|
|
@ -50,6 +50,20 @@ fn generated_roots_reject_governance_regressions() {
|
|||
"occurred_at": "2026-07-15T00:00:00Z",
|
||||
"unexpected": true
|
||||
}));
|
||||
let paths: Vec<Value> = (0..=10_000)
|
||||
.map(|index| Value::String(format!("file-{index}")))
|
||||
.collect();
|
||||
assert_invalid::<JobSubmission>(json!({
|
||||
"source": {
|
||||
"kind": "hugging_face",
|
||||
"repository_type": "model",
|
||||
"repository_id": "owner/repository",
|
||||
"revision": "main",
|
||||
"selection": {
|
||||
"paths": paths
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
fn assert_all<T: DeserializeOwned>(values: &Value) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue