gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Sutichaykuna

Validate tag when deserializing values (#805)

Signed-off-by: Nico Burns <nico@nicoburns.com>

bd0150f5fca7eadd62553898d3b064ccc3c54897 · ruwaq Nico Burns · (1 wata ñawpaq) · tayta 8d2a036c1 · kay commitpi sach'ata qhaway

Semántico sayk'uy · 6

src/style/compact_length.rs

src/style/dimension.rs

src/style/grid.rs

3 qillqakuna · +116 −8

diff --git a/src/style/compact_length.rs b/src/style/compact_length.rs
index 7e6be88f8..89280f621 100644
--- a/src/style/compact_length.rs
+++ b/src/style/compact_length.rs
@@ -506,10 +506,21 @@ impl<'de> serde::Deserialize<'de> for CompactLength {
     {
         let bits: u64 = u64::deserialize(deserializer)?;
         let value = Self(CompactLengthInner::from_serialized(bits));
-        if value.is_calc() {
-            Err(serde::de::Error::custom("Cannot deserialize Calc value"))
-        } else {
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(
+            value.tag(),
+            CompactLength::LENGTH_TAG
+                | CompactLength::PERCENT_TAG
+                | CompactLength::AUTO_TAG
+                | CompactLength::MIN_CONTENT_TAG
+                | CompactLength::MAX_CONTENT_TAG
+                | CompactLength::FIT_CONTENT_PX_TAG
+                | CompactLength::FIT_CONTENT_PERCENT_TAG
+                | CompactLength::FR_TAG
+        ) {
             Ok(value)
+        } else {
+            Err(serde::de::Error::custom("Cannot deserialize Calc value"))
         }
     }
 }
diff --git a/src/style/dimension.rs b/src/style/dimension.rs
index 83cddd79b..2391d5ba3 100644
--- a/src/style/dimension.rs
+++ b/src/style/dimension.rs
@@ -7,7 +7,7 @@ use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero};
 ///
 /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
 #[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize))]
 pub struct LengthPercentage(pub(crate) CompactLength);
 impl TaffyZero for LengthPercentage {
     const ZERO: Self = Self(CompactLength::ZERO);
@@ -61,11 +61,27 @@ impl LengthPercentage {
     }
 }
 
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for LengthPercentage {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let inner = CompactLength::deserialize(deserializer)?;
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG) {
+            Ok(Self(inner))
+        } else {
+            Err(serde::de::Error::custom("Invalid tag"))
+        }
+    }
+}
+
 /// A unit of linear measurement
 ///
 /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
 #[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize))]
 pub struct LengthPercentageAuto(pub(crate) CompactLength);
 impl TaffyZero for LengthPercentageAuto {
     const ZERO: Self = Self(CompactLength::ZERO);
@@ -156,11 +172,27 @@ impl LengthPercentageAuto {
     }
 }
 
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for LengthPercentageAuto {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let inner = CompactLength::deserialize(deserializer)?;
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG | CompactLength::AUTO_TAG) {
+            Ok(Self(inner))
+        } else {
+            Err(serde::de::Error::custom("Invalid tag"))
+        }
+    }
+}
+
 /// A unit of linear measurement
 ///
 /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
 #[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize))]
 pub struct Dimension(pub(crate) CompactLength);
 impl TaffyZero for Dimension {
     const ZERO: Self = Self(CompactLength::ZERO);
@@ -259,6 +291,22 @@ impl Dimension {
     }
 }
 
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for Dimension {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let inner = CompactLength::deserialize(deserializer)?;
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG | CompactLength::AUTO_TAG) {
+            Ok(Self(inner))
+        } else {
+            Err(serde::de::Error::custom("Invalid tag"))
+        }
+    }
+}
+
 impl Rect<Dimension> {
     /// Create a new Rect with length values
     #[must_use]
diff --git a/src/style/grid.rs b/src/style/grid.rs
index 28c71dd6c..9f800a25b 100644
--- a/src/style/grid.rs
+++ b/src/style/grid.rs
@@ -366,7 +366,7 @@ impl Default for Line<GridPlacement> {
 /// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under.
 /// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
 #[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize))]
 pub struct MaxTrackSizingFunction(pub(crate) CompactLength);
 impl TaffyZero for MaxTrackSizingFunction {
     const ZERO: Self = Self(CompactLength::ZERO);
@@ -420,6 +420,31 @@ impl From<MinTrackSizingFunction> for MaxTrackSizingFunction {
         Self(input.0)
     }
 }
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for MaxTrackSizingFunction {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let inner = CompactLength::deserialize(deserializer)?;
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(
+            inner.tag(),
+            CompactLength::LENGTH_TAG
+                | CompactLength::PERCENT_TAG
+                | CompactLength::AUTO_TAG
+                | CompactLength::MIN_CONTENT_TAG
+                | CompactLength::MAX_CONTENT_TAG
+                | CompactLength::FIT_CONTENT_PX_TAG
+                | CompactLength::FIT_CONTENT_PERCENT_TAG
+                | CompactLength::FR_TAG
+        ) {
+            Ok(Self(inner))
+        } else {
+            Err(serde::de::Error::custom("Invalid tag"))
+        }
+    }
+}
 
 impl MaxTrackSizingFunction {
     /// An absolute length in some abstract units. Users of Taffy may define what they correspond
@@ -637,7 +662,7 @@ impl MaxTrackSizingFunction {
 /// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under.
 /// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
 #[derive(Copy, Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize))]
 pub struct MinTrackSizingFunction(pub(crate) CompactLength);
 impl TaffyZero for MinTrackSizingFunction {
     const ZERO: Self = Self(CompactLength::ZERO);
@@ -676,6 +701,30 @@ impl From<Dimension> for MinTrackSizingFunction {
         Self(input.0)
     }
 }
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for MinTrackSizingFunction {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let inner = CompactLength::deserialize(deserializer)?;
+        // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
+        if matches!(
+            inner.tag(),
+            CompactLength::LENGTH_TAG
+                | CompactLength::PERCENT_TAG
+                | CompactLength::AUTO_TAG
+                | CompactLength::MIN_CONTENT_TAG
+                | CompactLength::MAX_CONTENT_TAG
+                | CompactLength::FIT_CONTENT_PX_TAG
+                | CompactLength::FIT_CONTENT_PERCENT_TAG
+        ) {
+            Ok(Self(inner))
+        } else {
+            Err(serde::de::Error::custom("Invalid tag"))
+        }
+    }
+}
 
 impl MinTrackSizingFunction {
     /// An absolute length in some abstract units. Users of Taffy may define what they correspond