From aa10025366a0f1425f10898f2854926a42eaed37 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Fri, 3 Mar 2023 14:48:04 +0100 Subject: [PATCH] schema: guard property string constraint checking StringSchema::check_constraint runs `parse_property_string` for property strings, but when we deserialize a `PropertyString` we immediately follow that up with deserializing it using the schema, so there's no need to check it beforehand. Signed-off-by: Wolfgang Bumiller --- proxmox-schema/src/de/mod.rs | 28 ++++++++++++++++++++++++--- proxmox-schema/src/property_string.rs | 10 ++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/proxmox-schema/src/de/mod.rs b/proxmox-schema/src/de/mod.rs index 25efb420..973bb95e 100644 --- a/proxmox-schema/src/de/mod.rs +++ b/proxmox-schema/src/de/mod.rs @@ -1,6 +1,7 @@ //! Property string deserialization. use std::borrow::Cow; +use std::cell::Cell; use std::fmt; use std::ops::Range; @@ -18,6 +19,25 @@ pub use extract::ExtractValueDeserializer; use cow3::{str_slice_to_range, Cow3}; +// Used to disable calling `check_constraints` on a `StringSchema` if it is being deserialized +// for a `PropertyString`, which performs its own checking. +thread_local! { + static IN_PROPERTY_STRING: Cell = Cell::new(false); +} + +pub(crate) struct InPropertyStringGuard; + +pub(crate) fn set_in_property_string() -> InPropertyStringGuard { + IN_PROPERTY_STRING.with(|v| v.set(true)); + InPropertyStringGuard +} + +impl Drop for InPropertyStringGuard { + fn drop(&mut self) { + IN_PROPERTY_STRING.with(|v| v.set(false)); + } +} + #[derive(Debug)] pub struct Error(Cow<'static, str>); @@ -86,9 +106,11 @@ impl<'de, 'i> SchemaDeserializer<'de, 'i> { where V: de::Visitor<'de>, { - schema - .check_constraints(&self.input) - .map_err(|err| Error::invalid(err))?; + if !IN_PROPERTY_STRING.with(|v| v.get()) { + schema + .check_constraints(&self.input) + .map_err(|err| Error::invalid(err))?; + } match self.input { Cow3::Original(input) => visitor.visit_borrowed_str(input), Cow3::Intermediate(input) => visitor.visit_str(input), diff --git a/proxmox-schema/src/property_string.rs b/proxmox-schema/src/property_string.rs index cf18a18a..e02b7161 100644 --- a/proxmox-schema/src/property_string.rs +++ b/proxmox-schema/src/property_string.rs @@ -267,9 +267,11 @@ where where D: serde::Deserializer<'de>, { + use crate::de::{set_in_property_string, InPropertyStringGuard}; + use std::marker::PhantomData; - struct V(PhantomData); + struct V(InPropertyStringGuard, PhantomData); impl<'de, T> serde::de::Visitor<'de> for V where @@ -292,6 +294,7 @@ where where E: serde::de::Error, { + drop(self); // unset IN_PROPERTY_STRING T::deserialize(crate::de::SchemaDeserializer::new(s, &T::API_SCHEMA)) .map_err(|err| E::custom(err.to_string())) } @@ -300,12 +303,15 @@ where where E: serde::de::Error, { + drop(self); // unset IN_PROPERTY_STRING T::deserialize(crate::de::SchemaDeserializer::new(s, &T::API_SCHEMA)) .map_err(|err| E::custom(err.to_string())) } } - deserializer.deserialize_string(V(PhantomData)).map(Self) + deserializer + .deserialize_string(V(set_in_property_string(), PhantomData)) + .map(Self) } }