Skip to main content

netget/server/gnmi/
json.rs

1//! Bounded JSON values, decoded before any gNMI JSON bytes reach a model event.
2use serde::de::{DeserializeSeed, MapAccess, SeqAccess, Visitor};
3use serde_json::{Map, Number, Value};
4use tonic::Status;
5pub fn parse(bytes: &[u8]) -> Result<Value, Status> {
6    parse_with_budget(bytes, &mut 0)
7}
8pub(super) fn parse_with_budget(bytes: &[u8], nodes: &mut usize) -> Result<Value, Status> {
9    if bytes.len() > super::codec::MAX_VALUE_BYTES {
10        return Err(Status::resource_exhausted("gNMI JSON value exceeds 64 KiB"));
11    }
12    let mut decoder = serde_json::Deserializer::from_slice(bytes);
13    let mut deepest = 0usize;
14    let value = Seed {
15        nodes,
16        depth: 0,
17        deepest: &mut deepest,
18    }
19    .deserialize(&mut decoder)
20    .map_err(|_| {
21        if *nodes > super::codec::MAX_NODES || deepest > super::codec::MAX_DEPTH {
22            Status::resource_exhausted("gNMI JSON node/depth bound")
23        } else {
24            Status::invalid_argument("invalid gNMI JSON or text/key bound")
25        }
26    })?;
27    decoder
28        .end()
29        .map_err(|_| Status::invalid_argument("trailing JSON value"))?;
30    Ok(value)
31}
32struct Seed<'a> {
33    nodes: &'a mut usize,
34    depth: usize,
35    deepest: &'a mut usize,
36}
37impl<'de> DeserializeSeed<'de> for Seed<'_> {
38    type Value = Value;
39    fn deserialize<D: serde::Deserializer<'de>>(self, decoder: D) -> Result<Value, D::Error> {
40        *self.nodes += 1;
41        *self.deepest = (*self.deepest).max(self.depth);
42        if *self.nodes > super::codec::MAX_NODES || self.depth > super::codec::MAX_DEPTH {
43            return Err(serde::de::Error::custom("JSON node/depth bound"));
44        }
45        decoder.deserialize_any(self)
46    }
47}
48impl<'de> Visitor<'de> for Seed<'_> {
49    type Value = Value;
50    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
51        f.write_str("bounded JSON value")
52    }
53    fn visit_unit<E: serde::de::Error>(self) -> Result<Value, E> {
54        Ok(Value::Null)
55    }
56    fn visit_bool<E: serde::de::Error>(self, v: bool) -> Result<Value, E> {
57        Ok(Value::Bool(v))
58    }
59    fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Value, E> {
60        Ok(v.into())
61    }
62    fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Value, E> {
63        Ok(v.into())
64    }
65    fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<Value, E> {
66        Number::from_f64(v)
67            .map(Value::Number)
68            .ok_or_else(|| E::custom("nonfinite JSON number"))
69    }
70    fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Value, E> {
71        if v.len() > super::codec::MAX_VALUE_BYTES {
72            return Err(E::custom("JSON text bound"));
73        }
74        Ok(Value::String(v.into()))
75    }
76    fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Value, E> {
77        self.visit_str(&v)
78    }
79    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Value, A::Error> {
80        let mut result = Vec::new();
81        while let Some(v) = seq.next_element_seed(Seed {
82            nodes: self.nodes,
83            depth: self.depth + 1,
84            deepest: self.deepest,
85        })? {
86            result.push(v);
87        }
88        Ok(Value::Array(result))
89    }
90    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Value, A::Error> {
91        let mut result = Map::new();
92        while let Some(key) = map.next_key::<String>()? {
93            if key.len() > 256 || result.contains_key(&key) {
94                return Err(serde::de::Error::custom("JSON key bound or duplicate"));
95            }
96            *self.nodes += 1;
97            if *self.nodes > super::codec::MAX_NODES {
98                return Err(serde::de::Error::custom("JSON node bound"));
99            }
100            let value = map.next_value_seed(Seed {
101                nodes: self.nodes,
102                depth: self.depth + 1,
103                deepest: self.deepest,
104            })?;
105            result.insert(key, value);
106        }
107        Ok(Value::Object(result))
108    }
109}