Skip to main content

maxminddb/
decoder.rs

1use core::convert::TryInto;
2
3use serde::{
4    de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor},
5    forward_to_deserialize_any,
6};
7
8use super::{
9    DecodeLimits, MaxMindDBError,
10    MaxMindDBError::{DecodingError, InvalidDatabaseError, ResourceLimit},
11};
12
13fn to_usize(base: u8, bytes: &[u8]) -> usize {
14    bytes.iter().fold(base as usize, |acc, &b| (acc << 8) | b as usize)
15}
16
17enum Value<'a, 'de> {
18    Bytes(&'de [u8]),
19    String(&'de str),
20    Bool(bool),
21    I32(i32),
22    U16(u16),
23    U32(u32),
24    U64(u64),
25    U128(u128),
26    F64(f64),
27    F32(f32),
28    Map(MapAccessor<'a, 'de>),
29    Array(ArrayAccess<'a, 'de>),
30}
31
32/// Decodes MaxMind DB data-section values into Serde types.
33///
34/// A decoder tracks the resource limits configured on the owning [`Reader`], so
35/// decoding a hostile or corrupt database returns
36/// [`MaxMindDBError::ResourceLimit`] instead of recursing without bound or
37/// expanding a small entry into a huge structure.
38///
39/// [`Reader`]: crate::Reader
40#[derive(Debug)]
41pub struct Decoder<'de> {
42    buf: &'de [u8],
43    current_ptr: usize,
44    limits: DecodeLimits,
45    depth: usize,
46    values_left: usize,
47    payload_left: usize,
48}
49
50impl<'de> Decoder<'de> {
51    /// Create a decoder starting at `start_ptr` with the default resource limits.
52    pub fn new(buf: &'de [u8], start_ptr: usize) -> Decoder<'de> {
53        Decoder::with_limits(buf, start_ptr, DecodeLimits::default())
54    }
55
56    /// Create a decoder starting at `start_ptr` with explicit resource limits.
57    ///
58    /// See [`DecodeLimits`] for the meaning of each limit and the recommended
59    /// defaults.
60    pub fn with_limits(buf: &'de [u8], start_ptr: usize, limits: DecodeLimits) -> Decoder<'de> {
61        Decoder {
62            buf,
63            current_ptr: start_ptr,
64            values_left: limits.max_values,
65            payload_left: limits.max_payload_bytes,
66            limits,
67            depth: 0,
68        }
69    }
70
71    fn ensure_available(&self, n: usize) -> DecodeResult<()> {
72        match self.current_ptr.checked_add(n) {
73            Some(end) if end <= self.buf.len() => Ok(()),
74            _ => Err(InvalidDatabaseError(format!(
75                "truncated data: expected {} bytes at offset {} but buffer length is {}",
76                n,
77                self.current_ptr,
78                self.buf.len()
79            ))),
80        }
81    }
82
83    fn eat_byte(&mut self) -> DecodeResult<u8> {
84        self.ensure_available(1)?;
85        let b = self.buf[self.current_ptr];
86        self.current_ptr += 1;
87        Ok(b)
88    }
89
90    fn size_from_ctrl_byte(&mut self, ctrl_byte: u8) -> DecodeResult<usize> {
91        let size = (ctrl_byte & 0x1f) as usize;
92
93        let bytes_to_read = size.saturating_sub(28);
94
95        self.ensure_available(bytes_to_read)?;
96        let new_offset = self.current_ptr + bytes_to_read;
97        let size_bytes = &self.buf[self.current_ptr..new_offset];
98        self.current_ptr = new_offset;
99
100        Ok(match size {
101            s if s < 29 => s,
102            29 => 29_usize + size_bytes[0] as usize,
103            30 => 285_usize + to_usize(0, size_bytes),
104            _ => 65_821_usize + to_usize(0, size_bytes),
105        })
106    }
107
108    /// Returns the size and type number of the value at the cursor.
109    ///
110    /// The type is returned as a `u16` so that an extended type byte of
111    /// `249..=255` (which would overflow a `u8` when `7` is added) is reported
112    /// as an unknown type instead of wrapping to an unrelated type.
113    fn size_and_type(&mut self) -> DecodeResult<(usize, u16)> {
114        let ctrl_byte = self.eat_byte()?;
115        let mut type_num = u16::from(ctrl_byte >> 5);
116        if type_num == 0 {
117            type_num = u16::from(self.eat_byte()?) + 7;
118        }
119        let size = self.size_from_ctrl_byte(ctrl_byte)?;
120        Ok((size, type_num))
121    }
122
123    /// Charges one logical value against the value budget.
124    fn charge_value(&mut self) -> DecodeResult<()> {
125        if self.values_left == 0 {
126            return Err(ResourceLimit(format!(
127                "decoded value count exceeded the configured limit of {}",
128                self.limits.max_values
129            )));
130        }
131        self.values_left -= 1;
132        Ok(())
133    }
134
135    /// Charges `n` bytes of string or byte payload against the payload budget.
136    fn charge_payload(&mut self, n: usize) -> DecodeResult<()> {
137        match self.payload_left.checked_sub(n) {
138            Some(rest) => {
139                self.payload_left = rest;
140                Ok(())
141            }
142            None => Err(ResourceLimit(format!(
143                "decoded string/bytes payload exceeded the configured limit of {} bytes",
144                self.limits.max_payload_bytes
145            ))),
146        }
147    }
148
149    /// Increases the current nesting depth and rejects values that are nested
150    /// more deeply than the configured limit.
151    fn enter_depth(&mut self) -> DecodeResult<()> {
152        self.depth = self.depth.saturating_add(1);
153        if self.depth > self.limits.max_depth {
154            return Err(ResourceLimit(format!(
155                "data structure nesting exceeded the configured maximum depth of {}",
156                self.limits.max_depth
157            )));
158        }
159        Ok(())
160    }
161
162    /// Decodes the next value and hands it to `visitor`.
163    ///
164    /// The nesting depth is restored on every exit path, so sibling values do
165    /// not accumulate depth.
166    fn decode_any<V: Visitor<'de>>(&mut self, visitor: V) -> DecodeResult<V::Value> {
167        self.charge_value()?;
168        let saved_depth = self.depth;
169        self.enter_depth()?;
170        let result = self.decode_any_inner(visitor);
171        self.depth = saved_depth;
172        result
173    }
174
175    fn decode_any_inner<V: Visitor<'de>>(&mut self, visitor: V) -> DecodeResult<V::Value> {
176        // A data value may be a chain of pointers. Follow it iteratively (so a
177        // chain cannot exhaust the call stack) and remember where to restore
178        // the cursor once the final value has been decoded.
179        let mut restore_ptr = None;
180
181        loop {
182            let (size, type_num) = self.size_and_type()?;
183
184            if type_num == 1 {
185                let target = self.decode_pointer(size)?;
186                let after_pointer = self.current_ptr;
187                if target >= self.buf.len() {
188                    return Err(InvalidDatabaseError(format!(
189                        "pointer at offset {} points beyond end of buffer ({})",
190                        after_pointer - 1,
191                        target
192                    )));
193                }
194                // Following a pointer counts as one level of nesting. This
195                // bounds both unbounded pointer chains and pointer cycles.
196                self.enter_depth()?;
197                if restore_ptr.is_none() {
198                    restore_ptr = Some(after_pointer);
199                }
200                self.current_ptr = target;
201                continue;
202            }
203
204            let value = self.decode_value(size, type_num)?;
205            let result = match value {
206                Value::Bool(x) => visitor.visit_bool(x),
207                Value::Bytes(x) => visitor.visit_borrowed_bytes(x),
208                Value::String(x) => visitor.visit_borrowed_str(x),
209                Value::I32(x) => visitor.visit_i32(x),
210                Value::U16(x) => visitor.visit_u16(x),
211                Value::U32(x) => visitor.visit_u32(x),
212                Value::U64(x) => visitor.visit_u64(x),
213                Value::U128(x) => visitor.visit_u128(x),
214                Value::F64(x) => visitor.visit_f64(x),
215                Value::F32(x) => visitor.visit_f32(x),
216                Value::Map(x) => visitor.visit_map(x),
217                Value::Array(x) => visitor.visit_seq(x),
218            };
219
220            if let Some(ptr) = restore_ptr {
221                self.current_ptr = ptr;
222            }
223            return result;
224        }
225    }
226
227    fn decode_value(&mut self, size: usize, type_num: u16) -> DecodeResult<Value<'_, 'de>> {
228        Ok(match type_num {
229            2 => Value::String(self.decode_string(size)?),
230            3 => Value::F64(self.decode_double(size)?),
231            4 => Value::Bytes(self.decode_bytes(size)?),
232            5 => Value::U16(self.decode_uint16(size)?),
233            6 => Value::U32(self.decode_uint32(size)?),
234            7 => self.decode_map(size)?,
235            8 => Value::I32(self.decode_int(size)?),
236            9 => Value::U64(self.decode_uint64(size)?),
237            10 => Value::U128(self.decode_uint128(size)?),
238            11 => self.decode_array(size)?,
239            14 => Value::Bool(self.decode_bool(size)?),
240            15 => Value::F32(self.decode_float(size)?),
241            u => return Err(InvalidDatabaseError(format!("Unknown data type: {u:?}"))),
242        })
243    }
244
245    fn decode_array(&mut self, size: usize) -> DecodeResult<Value<'_, 'de>> {
246        // Refuse a declared length that cannot fit the remaining budget before
247        // any storage is reserved for it.
248        if size > self.values_left {
249            return Err(ResourceLimit(format!(
250                "array of {size} entries exceeds the remaining decoded value budget of {}",
251                self.values_left
252            )));
253        }
254        Ok(Value::Array(ArrayAccess {
255            de: self,
256            count: size,
257        }))
258    }
259
260    fn decode_bool(&mut self, size: usize) -> DecodeResult<bool> {
261        match size {
262            0 | 1 => Ok(size != 0),
263            s => Err(InvalidDatabaseError(format!("bool of size {s:?}"))),
264        }
265    }
266
267    fn decode_bytes(&mut self, size: usize) -> DecodeResult<&'de [u8]> {
268        self.charge_payload(size)?;
269        let new_offset = self
270            .current_ptr
271            .checked_add(size)
272            .ok_or_else(|| InvalidDatabaseError(format!("bytes length {size} overflows the buffer offset")))?;
273        self.ensure_available(size)?;
274        let u8_slice = &self.buf[self.current_ptr..new_offset];
275        self.current_ptr = new_offset;
276
277        Ok(u8_slice)
278    }
279
280    fn decode_float(&mut self, size: usize) -> DecodeResult<f32> {
281        self.ensure_available(size)?;
282        let new_offset = self.current_ptr + size;
283        let value: [u8; 4] = self.buf[self.current_ptr..new_offset]
284            .try_into()
285            .map_err(|_| InvalidDatabaseError(format!("float of size {:?}", new_offset - self.current_ptr)))?;
286        self.current_ptr = new_offset;
287        let float_value = f32::from_be_bytes(value);
288        Ok(float_value)
289    }
290
291    fn decode_double(&mut self, size: usize) -> DecodeResult<f64> {
292        self.ensure_available(size)?;
293        let new_offset = self.current_ptr + size;
294        let value: [u8; 8] = self.buf[self.current_ptr..new_offset]
295            .try_into()
296            .map_err(|_| InvalidDatabaseError(format!("double of size {:?}", new_offset - self.current_ptr)))?;
297        self.current_ptr = new_offset;
298        let float_value = f64::from_be_bytes(value);
299        Ok(float_value)
300    }
301
302    fn decode_uint64(&mut self, size: usize) -> DecodeResult<u64> {
303        match size {
304            s if s <= 8 => {
305                self.ensure_available(size)?;
306                let new_offset = self.current_ptr + size;
307
308                let value = self.buf[self.current_ptr..new_offset]
309                    .iter()
310                    .fold(0_u64, |acc, &b| (acc << 8) | u64::from(b));
311                self.current_ptr = new_offset;
312                Ok(value)
313            }
314            s => Err(InvalidDatabaseError(format!("u64 of size {s:?}"))),
315        }
316    }
317
318    fn decode_uint128(&mut self, size: usize) -> DecodeResult<u128> {
319        match size {
320            s if s <= 16 => {
321                self.ensure_available(size)?;
322                let new_offset = self.current_ptr + size;
323
324                let value = self.buf[self.current_ptr..new_offset]
325                    .iter()
326                    .fold(0_u128, |acc, &b| (acc << 8) | u128::from(b));
327                self.current_ptr = new_offset;
328                Ok(value)
329            }
330            s => Err(InvalidDatabaseError(format!("u128 of size {s:?}"))),
331        }
332    }
333
334    fn decode_uint32(&mut self, size: usize) -> DecodeResult<u32> {
335        match size {
336            s if s <= 4 => {
337                self.ensure_available(size)?;
338                let new_offset = self.current_ptr + size;
339
340                let value = self.buf[self.current_ptr..new_offset]
341                    .iter()
342                    .fold(0_u32, |acc, &b| (acc << 8) | u32::from(b));
343                self.current_ptr = new_offset;
344                Ok(value)
345            }
346            s => Err(InvalidDatabaseError(format!("u32 of size {s:?}"))),
347        }
348    }
349
350    fn decode_uint16(&mut self, size: usize) -> DecodeResult<u16> {
351        match size {
352            s if s <= 2 => {
353                self.ensure_available(size)?;
354                let new_offset = self.current_ptr + size;
355
356                let value = self.buf[self.current_ptr..new_offset]
357                    .iter()
358                    .fold(0_u16, |acc, &b| (acc << 8) | u16::from(b));
359                self.current_ptr = new_offset;
360                Ok(value)
361            }
362            s => Err(InvalidDatabaseError(format!("u16 of size {s:?}"))),
363        }
364    }
365
366    fn decode_int(&mut self, size: usize) -> DecodeResult<i32> {
367        match size {
368            s if s <= 4 => {
369                self.ensure_available(size)?;
370                let new_offset = self.current_ptr + size;
371
372                let value = self.buf[self.current_ptr..new_offset]
373                    .iter()
374                    .fold(0_i32, |acc, &b| (acc << 8) | i32::from(b));
375                self.current_ptr = new_offset;
376                Ok(value)
377            }
378            s => Err(InvalidDatabaseError(format!("int32 of size {s:?}"))),
379        }
380    }
381
382    fn decode_map(&mut self, size: usize) -> DecodeResult<Value<'_, 'de>> {
383        let entries = size
384            .checked_mul(2)
385            .ok_or_else(|| InvalidDatabaseError("map size overflow".to_owned()))?;
386        // A map entry decodes a key and a value, so a declared size larger than
387        // the remaining budget can never succeed. Reject it before reserving
388        // anything for it.
389        if entries > self.values_left {
390            return Err(ResourceLimit(format!(
391                "map of {size} entries exceeds the remaining decoded value budget of {}",
392                self.values_left
393            )));
394        }
395        Ok(Value::Map(MapAccessor {
396            de: self,
397            count: entries,
398        }))
399    }
400
401    fn decode_pointer(&mut self, size: usize) -> DecodeResult<usize> {
402        let pointer_value_offset = [0, 0, 2048, 526_336, 0];
403        let pointer_size = ((size >> 3) & 0x3) + 1;
404        self.ensure_available(pointer_size)?;
405        let new_offset = self.current_ptr + pointer_size;
406        let pointer_bytes = &self.buf[self.current_ptr..new_offset];
407        self.current_ptr = new_offset;
408
409        let base = if pointer_size == 4 { 0 } else { (size & 0x7) as u8 };
410        let unpacked = to_usize(base, pointer_bytes);
411
412        Ok(unpacked + pointer_value_offset[pointer_size])
413    }
414
415    fn decode_string(&mut self, size: usize) -> DecodeResult<&'de str> {
416        use std::str::from_utf8;
417
418        self.charge_payload(size)?;
419        let new_offset = self
420            .current_ptr
421            .checked_add(size)
422            .ok_or_else(|| InvalidDatabaseError(format!("string length {size} overflows the buffer offset")))?;
423        self.ensure_available(size)?;
424        let bytes = &self.buf[self.current_ptr..new_offset];
425        self.current_ptr = new_offset;
426        match from_utf8(bytes) {
427            Ok(v) => Ok(v),
428            Err(_) => Err(InvalidDatabaseError("error decoding string".to_owned())),
429        }
430    }
431}
432
433pub type DecodeResult<T> = Result<T, MaxMindDBError>;
434
435impl<'de: 'a, 'a> de::Deserializer<'de> for &'a mut Decoder<'de> {
436    type Error = MaxMindDBError;
437
438    fn deserialize_any<V>(self, visitor: V) -> DecodeResult<V::Value>
439    where
440        V: Visitor<'de>,
441    {
442        self.decode_any(visitor)
443    }
444
445    fn deserialize_option<V>(self, visitor: V) -> DecodeResult<V::Value>
446    where
447        V: Visitor<'de>,
448    {
449        visitor.visit_some(self)
450    }
451
452    forward_to_deserialize_any! {
453        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
454        bytes byte_buf unit unit_struct newtype_struct seq tuple
455        tuple_struct map struct enum identifier ignored_any
456    }
457}
458
459struct ArrayAccess<'a, 'de: 'a> {
460    de: &'a mut Decoder<'de>,
461    count: usize,
462}
463
464impl<'de, 'a> SeqAccess<'de> for ArrayAccess<'a, 'de> {
465    type Error = MaxMindDBError;
466
467    fn next_element_seed<T>(&mut self, seed: T) -> DecodeResult<Option<T::Value>>
468    where
469        T: DeserializeSeed<'de>,
470    {
471        if self.count == 0 {
472            return Ok(None);
473        }
474        self.count -= 1;
475
476        seed.deserialize(&mut *self.de).map(Some)
477    }
478}
479
480struct MapAccessor<'a, 'de: 'a> {
481    de: &'a mut Decoder<'de>,
482    count: usize,
483}
484
485impl<'de, 'a> MapAccess<'de> for MapAccessor<'a, 'de> {
486    type Error = MaxMindDBError;
487
488    fn next_key_seed<K>(&mut self, seed: K) -> DecodeResult<Option<K::Value>>
489    where
490        K: DeserializeSeed<'de>,
491    {
492        if self.count == 0 {
493            return Ok(None);
494        }
495        self.count -= 1;
496
497        seed.deserialize(&mut *self.de).map(Some)
498    }
499
500    fn next_value_seed<V>(&mut self, seed: V) -> DecodeResult<V::Value>
501    where
502        V: DeserializeSeed<'de>,
503    {
504        if self.count == 0 {
505            return Err(DecodingError("no more entries".to_owned()));
506        }
507        self.count -= 1;
508
509        seed.deserialize(&mut *self.de)
510    }
511}