Skip to main content

cuprate_epee_encoding/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2//! Epee Encoding
3//!
4//! This library contains the Epee binary format found in Monero, unlike other
5//! crates this crate does not use serde.
6//!
7//! See [`epee_object`] for how to easily implement [`EpeeObject`] for your types.
8//!
9//! example without macro:
10//! ```rust
11//! # use cuprate_epee_encoding::{EpeeObject, EpeeObjectBuilder, read_epee_value, write_field, to_bytes, from_bytes};
12//! # use bytes::{Buf, BufMut};
13//!
14//! pub struct Test {
15//!     val: u64
16//! }
17//!
18//! #[derive(Default)]
19//! pub struct __TestEpeeBuilder {
20//!     val: Option<u64>,
21//! }
22//!
23//! impl EpeeObjectBuilder<Test> for __TestEpeeBuilder {
24//!     fn add_field<B: Buf>(&mut self, name: &str, r: &mut B) -> cuprate_epee_encoding::error::Result<bool> {
25//!         match name {
26//!             "val" => {self.val = Some(read_epee_value(r, Default::default())?);}
27//!             _ => return Ok(false),
28//!         }
29//!         Ok(true)
30//!     }
31//!
32//!     fn finish(self) -> cuprate_epee_encoding::error::Result<Test> {
33//!         Ok(
34//!             Test {
35//!                 val: self.val.ok_or_else(|| cuprate_epee_encoding::error::Error::Format("Required field was not found!"))?
36//!             }
37//!         )
38//!     }
39//! }
40//!
41//! impl EpeeObject for Test {
42//!     type Builder = __TestEpeeBuilder;
43//!
44//!     fn number_of_fields(&self) -> u64 {
45//!         1
46//!     }
47//!
48//!     fn write_fields<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::error::Result<()> {
49//!        // write the fields
50//!        write_field(self.val, "val", w)
51//!    }
52//! }
53//!
54//!
55//! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
56//! let val: Test = from_bytes(&mut data.as_slice()).unwrap();
57//! let data = to_bytes(val).unwrap();
58//!
59//!
60//! ```
61
62#[cfg(test)]
63use hex as _;
64
65extern crate alloc;
66
67use alloc::string::ToString;
68use core::str::from_utf8 as str_from_utf8;
69
70use bytes::{Buf, BufMut, Bytes, BytesMut};
71
72pub mod container_as_blob;
73pub mod error;
74mod io;
75pub mod macros;
76pub mod marker;
77mod value;
78mod varint;
79
80pub use error::*;
81use io::*;
82pub use marker::{InnerMarker, Marker};
83pub use value::{EpeeValue, EpeeValueLimits};
84pub use varint::{read_varint, write_varint};
85
86/// Header that needs to be at the beginning of every binary blob that follows
87/// this binary serialization format.
88const HEADER: &[u8] = b"\x01\x11\x01\x01\x01\x01\x02\x01\x01";
89/// The maximum length a byte array (marked as a string) can be.
90const MAX_STRING_LEN_POSSIBLE: usize = 2000000000;
91/// The maximum depth of skipped objects.
92const MAX_DEPTH_OF_SKIPPED_OBJECTS: u8 = 20;
93/// The maximum number of fields in an object.
94const MAX_NUM_FIELDS: u64 = 1000;
95
96/// A trait for an object that can build a type `T` from the epee format.
97pub trait EpeeObjectBuilder<T>: Default + Sized {
98    /// Called when a field names has been read no other bytes following the field
99    /// name will have been read.
100    ///
101    /// Returns a bool if true then the field has been read otherwise the field is not
102    /// needed and has not been read.
103    fn add_field<B: Buf>(&mut self, name: &str, b: &mut B) -> Result<bool>;
104
105    /// Called when the number of fields has been read.
106    fn finish(self) -> Result<T>;
107}
108
109/// A trait for an object that can be turned into epee bytes.
110pub trait EpeeObject: Sized {
111    type Builder: EpeeObjectBuilder<Self>;
112
113    /// Returns the number of fields to be encoded.
114    fn number_of_fields(&self) -> u64;
115
116    /// write the objects fields into the writer.
117    fn write_fields<B: BufMut>(self, w: &mut B) -> Result<()>;
118}
119
120/// Read the object `T` from a byte array.
121pub fn from_bytes<T: EpeeObject, B: Buf>(buf: &mut B) -> Result<T> {
122    read_head_object(buf)
123}
124
125/// Turn the object into epee bytes.
126pub fn to_bytes<T: EpeeObject>(val: T) -> Result<BytesMut> {
127    let mut buf = BytesMut::new();
128    write_head_object(val, &mut buf)?;
129    Ok(buf)
130}
131
132fn read_header<B: Buf>(r: &mut B) -> Result<()> {
133    let buf = checked_read(r, |b: &mut B| b.copy_to_bytes(HEADER.len()), HEADER.len())?;
134
135    if &*buf != HEADER {
136        return Err(Error::Format("Data does not contain header"));
137    }
138    Ok(())
139}
140
141fn write_header<B: BufMut>(w: &mut B) -> Result<()> {
142    checked_write(w, BufMut::put_slice, HEADER, HEADER.len())
143}
144
145fn write_head_object<T: EpeeObject, B: BufMut>(val: T, w: &mut B) -> Result<()> {
146    write_header(w)?;
147    val.write(w)
148}
149
150fn read_head_object<T: EpeeObject, B: Buf>(r: &mut B) -> Result<T> {
151    read_header(r)?;
152    let mut skipped_objects = 0;
153    read_object(r, &mut skipped_objects)
154}
155
156fn read_field_name_bytes<B: Buf>(r: &mut B) -> Result<Bytes> {
157    let len: usize = checked_read_primitive(r, Buf::get_u8)?.into();
158
159    if len == 0 {
160        return Err(Error::Format("Field name has a length of 0"));
161    }
162
163    checked_read(r, |b: &mut B| b.copy_to_bytes(len), len)
164}
165
166fn write_field_name<B: BufMut>(val: &str, w: &mut B) -> Result<()> {
167    checked_write_primitive(w, BufMut::put_u8, val.len().try_into()?)?;
168    let slice = val.as_bytes();
169    checked_write(w, BufMut::put_slice, slice, slice.len())
170}
171
172/// Write an epee field.
173pub fn write_field<T: EpeeValue, B: BufMut>(val: T, field_name: &str, w: &mut B) -> Result<()> {
174    if val.should_write() {
175        write_field_name(field_name, w)?;
176        write_epee_value(val, w)?;
177    }
178    Ok(())
179}
180
181fn read_object<T: EpeeObject, B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<T> {
182    let mut object_builder = T::Builder::default();
183
184    let number_o_field = read_varint(r)?;
185
186    if number_o_field > MAX_NUM_FIELDS {
187        return Err(Error::Format(
188            "Data has object with more fields than the maximum allowed",
189        ));
190    }
191
192    for _ in 0..number_o_field {
193        let field_name_bytes = read_field_name_bytes(r)?;
194        let field_name = str_from_utf8(&field_name_bytes)?;
195
196        if !object_builder.add_field(field_name, r)? {
197            skip_epee_value(r, skipped_objects)?;
198        }
199    }
200    object_builder.finish()
201}
202
203/// Read a marker from the [`Buf`], this function should only be used for
204/// custom serialisation based on the marker otherwise just use [`read_epee_value`].
205pub fn read_marker<B: Buf>(r: &mut B) -> Result<Marker> {
206    Marker::try_from(checked_read_primitive(r, Buf::get_u8)?)
207}
208
209/// Read an epee value from the stream, an epee value is the part after the key
210/// including the marker.
211pub fn read_epee_value<T: EpeeValue, B: Buf>(r: &mut B, limits: EpeeValueLimits) -> Result<T> {
212    let marker = read_marker(r)?;
213    T::read(r, &marker, limits)
214}
215
216/// Write an epee value to the stream, an epee value is the part after the key
217/// including the marker.
218fn write_epee_value<T: EpeeValue, B: BufMut>(val: T, w: &mut B) -> Result<()> {
219    checked_write_primitive(w, BufMut::put_u8, T::MARKER.as_u8())?;
220    val.write(w)
221}
222
223/// Write a byte array to `w` with [`write_varint`].
224///
225/// This function:
226/// - Writes the length of `t`'s bytes into `w` using [`write_varint`]
227/// - Writes `t`'s bytes into `w`
228///
229/// It is used as the internal [`EpeeValue::write`]
230/// implementation of byte-like containers such as:
231/// - [`EpeeValue::<Vec<u8>>::write`]
232/// - [`EpeeValue::<String>::write`]
233///
234/// # Errors
235/// This will error if:
236/// - [`write_varint`] fails
237/// - `w` does not have enough capacity
238///
239/// # Example
240/// ```rust
241/// let t: [u8; 8] = [3, 0, 0, 0, 1, 0, 0, 0];
242/// let mut w = vec![];
243///
244/// cuprate_epee_encoding::write_bytes(t, &mut w).unwrap();
245///
246/// assert_eq!(w.len(), 9); // length of bytes + bytes
247/// assert_eq!(w[1..], t);
248/// ```
249pub fn write_bytes<T: AsRef<[u8]>, B: BufMut>(t: T, w: &mut B) -> Result<()> {
250    let bytes = t.as_ref();
251    let len = bytes.len();
252
253    write_varint(len, w)?;
254
255    if w.remaining_mut() < len {
256        return Err(Error::IO("Not enough capacity to write bytes"));
257    }
258
259    w.put_slice(bytes);
260
261    Ok(())
262}
263
264/// Write an [`Iterator`] of [`EpeeValue`]s to `w` with [`write_varint`].
265///
266/// This function:
267/// - Writes the length of the `iterator`, into `w` using [`write_varint`]
268/// - [`EpeeValue::write`]s each `T` of the iterator into `w`
269///
270/// It is used as the internal [`EpeeValue::write`]
271/// implementation of containers such as [`EpeeValue::<Vec<T>>::write`].
272///
273/// # Errors
274/// This will error if:
275/// - [`write_varint`] fails
276/// - [`EpeeValue::<T>::write`] fails
277///
278/// # Example
279/// ```rust
280/// let t: u64 = 3;
281/// let vec: Vec<u64> = vec![t, t];
282/// let mut w = vec![];
283///
284/// let iter: std::vec::IntoIter<u64> = vec.into_iter();
285/// cuprate_epee_encoding::write_iterator(iter, &mut w).unwrap();
286///
287/// assert_eq!(w.len(), 17);
288/// assert_eq!(w[1..9], [3, 0, 0, 0, 0, 0, 0, 0]);
289/// assert_eq!(w[9..], [3, 0, 0, 0, 0, 0, 0, 0]);
290/// ```
291pub fn write_iterator<T, I, B>(iterator: I, w: &mut B) -> Result<()>
292where
293    T: EpeeValue,
294    I: Iterator<Item = T> + ExactSizeIterator,
295    B: BufMut,
296{
297    write_varint(iterator.len(), w)?;
298    for item in iterator {
299        item.write(w)?;
300    }
301    Ok(())
302}
303
304/// A helper object builder that just skips every field.
305#[derive(Default)]
306struct SkipObjectBuilder;
307
308impl EpeeObjectBuilder<SkipObject> for SkipObjectBuilder {
309    fn add_field<B: Buf>(&mut self, _name: &str, _r: &mut B) -> Result<bool> {
310        Ok(false)
311    }
312
313    fn finish(self) -> Result<SkipObject> {
314        Ok(SkipObject)
315    }
316}
317
318/// A helper object that just skips every field.
319struct SkipObject;
320
321impl EpeeObject for SkipObject {
322    type Builder = SkipObjectBuilder;
323
324    fn number_of_fields(&self) -> u64 {
325        panic!("This is a helper function to use when de-serialising")
326    }
327
328    fn write_fields<B: BufMut>(self, _w: &mut B) -> Result<()> {
329        panic!("This is a helper function to use when de-serialising")
330    }
331}
332
333/// Skip an epee value, should be used when you do not need the value
334/// stored at a key.
335fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
336    let marker = read_marker(r)?;
337
338    let len = if marker.is_seq { read_varint(r)? } else { 1 };
339
340    if let Some(size) = marker.inner_marker.size() {
341        let bytes_to_skip = size
342            .checked_mul(len.try_into()?)
343            .ok_or(Error::Value("List is too big".to_string()))?;
344        return advance(bytes_to_skip, r);
345    }
346
347    for _ in 0..len {
348        match marker.inner_marker {
349            InnerMarker::I64
350            | InnerMarker::U64
351            | InnerMarker::F64
352            | InnerMarker::I32
353            | InnerMarker::U32
354            | InnerMarker::I16
355            | InnerMarker::U16
356            | InnerMarker::I8
357            | InnerMarker::U8
358            | InnerMarker::Bool => unreachable!("These types are constant size."),
359            InnerMarker::String => {
360                let len = read_varint(r)?;
361                advance(len, r)?;
362            }
363            InnerMarker::Object => {
364                *skipped_objects += 1;
365                if *skipped_objects > MAX_DEPTH_OF_SKIPPED_OBJECTS {
366                    return Err(Error::Format("Depth of skipped objects exceeded maximum"));
367                }
368                read_object::<SkipObject, _>(r, skipped_objects)?;
369                *skipped_objects -= 1;
370            }
371        }
372    }
373    Ok(())
374}
375
376fn advance<B: Buf>(n: usize, b: &mut B) -> Result<()> {
377    checked_read(b, |b: &mut B| b.advance(n), n)
378}
379
380/// Max upfront capacity when deserializing heap items.
381///
382/// Allocating upfront saves allocations however this must be limited otherwise an attacker can easily
383/// cause an OOM.
384const fn max_upfront_capacity<T>() -> usize {
385    2_000_000 / size_of::<T>()
386}