revm_bytecode/eof/
header.rs

1use super::{
2    decode_helpers::{consume_u16, consume_u8},
3    EofDecodeError,
4};
5use std::vec::Vec;
6
7/// EOF Header containing
8#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Ord, PartialOrd)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct EofHeader {
11    /// Size of EOF types section
12    ///
13    /// Types section includes num of input and outputs and max stack size.
14    pub types_size: u16,
15    /// Sizes of EOF code section
16    ///
17    /// Code size can't be zero.
18    pub code_sizes: Vec<u16>,
19    /// EOF Container size
20    ///
21    /// Container size can be zero.
22    pub container_sizes: Vec<u16>,
23    /// EOF data size
24    pub data_size: u16,
25    /// Sum code sizes
26    pub sum_code_sizes: usize,
27    /// Sum container sizes
28    pub sum_container_sizes: usize,
29}
30
31const KIND_TERMINAL: u8 = 0;
32const KIND_TYPES: u8 = 1;
33const KIND_CODE: u8 = 2;
34const KIND_CONTAINER: u8 = 3;
35const KIND_DATA: u8 = 4;
36
37#[inline]
38fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec<u16>, usize), EofDecodeError> {
39    // `num_sections`   2 bytes 0x0001-0xFFFF
40    // 16-bit unsigned big-endian integer denoting the number of the sections
41    let (input, num_sections) = consume_u16(input)?;
42    if num_sections == 0 {
43        return Err(EofDecodeError::NonSizes);
44    }
45    let num_sections = num_sections as usize;
46    let byte_size = num_sections * 2;
47    if input.len() < byte_size {
48        return Err(EofDecodeError::ShortInputForSizes);
49    }
50    let mut sizes = Vec::with_capacity(num_sections);
51    let mut sum = 0;
52    for i in 0..num_sections {
53        // `code_size`  2 bytes 0x0001-0xFFFF
54        // 16-bit unsigned big-endian integer denoting the length of the section content
55        let code_size = u16::from_be_bytes([input[i * 2], input[i * 2 + 1]]);
56        if code_size == 0 {
57            return Err(EofDecodeError::ZeroSize);
58        }
59        sum += code_size as usize;
60        sizes.push(code_size);
61    }
62
63    Ok((&input[byte_size..], sizes, sum))
64}
65
66impl EofHeader {
67    /// Gets the length of the header in bytes.
68    ///
69    /// It is minimum 15 bytes (there is at least one code section).
70    pub fn size(&self) -> usize {
71        2 + // Magic
72        1 + // Version
73        3 + // Types section
74        3 + // Code section
75        2 * self.code_sizes.len() + // `num_code_sections`
76        if self.container_sizes.is_empty() { 0 } else { 3 + 2 * self.container_sizes.len() } + // Container
77        3 + // Data section.
78        1 // Terminator
79    }
80
81    /// Returns index where data size starts.
82    ///
83    /// Data size is two bytes long.
84    pub fn data_size_raw_i(&self) -> usize {
85        // termination(1byte) + code size(2) bytes.
86        self.size() - 3
87    }
88
89    /// Returns number of types.
90    pub fn types_count(&self) -> usize {
91        self.types_size as usize / 4
92    }
93
94    /// Returns body size.
95    ///
96    /// It is sum of code sizes, container sizes and data size.
97    pub fn body_size(&self) -> usize {
98        self.types_size as usize
99            + self.sum_code_sizes
100            + self.sum_container_sizes
101            + self.data_size as usize
102    }
103
104    /// Returns raw size of the EOF.
105    pub fn eof_size(&self) -> usize {
106        self.size() + self.body_size()
107    }
108
109    /// Encodes EOF header into binary form.
110    pub fn encode(&self, buffer: &mut Vec<u8>) {
111        // `magic`	2 bytes	0xEF00	EOF prefix
112        buffer.extend_from_slice(&0xEF00u16.to_be_bytes());
113        // `version`	1 byte	0x01	EOF version
114        buffer.push(0x01);
115        // `kind_types`	1 byte	0x01	kind marker for types size section
116        buffer.push(KIND_TYPES);
117        // `types_size`	2 bytes	0x0004-0xFFFF
118        buffer.extend_from_slice(&self.types_size.to_be_bytes());
119        // `kind_code`	1 byte	0x02	kind marker for code size section
120        buffer.push(KIND_CODE);
121        // `code_sections_sizes`
122        buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes());
123        for size in &self.code_sizes {
124            buffer.extend_from_slice(&size.to_be_bytes());
125        }
126        // `kind_container_or_data`	1 byte	0x03 or 0x04	kind marker for container size section or data size section
127        if self.container_sizes.is_empty() {
128            buffer.push(KIND_DATA);
129        } else {
130            buffer.push(KIND_CONTAINER);
131            // `container_sections_sizes`
132            buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes());
133            for size in &self.container_sizes {
134                buffer.extend_from_slice(&size.to_be_bytes());
135            }
136            // `kind_data`	1 byte	0x04	kind marker for data size section
137            buffer.push(KIND_DATA);
138        }
139        // `data_size`	2 bytes	0x0000-0xFFFF	16-bit unsigned big-endian integer denoting the length of the data section content
140        buffer.extend_from_slice(&self.data_size.to_be_bytes());
141        // `terminator`	1 byte	0x00	marks the end of the EofHeader
142        buffer.push(KIND_TERMINAL);
143    }
144
145    /// Decodes EOF header from binary form.
146    pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> {
147        let mut header = EofHeader::default();
148
149        // `magic`	2 bytes	0xEF00	EOF prefix
150        let (input, kind) = consume_u16(input)?;
151        if kind != 0xEF00 {
152            return Err(EofDecodeError::InvalidEOFMagicNumber);
153        }
154
155        // `version`	1 byte	0x01	EOF version
156        let (input, version) = consume_u8(input)?;
157        if version != 0x01 {
158            return Err(EofDecodeError::InvalidEOFVersion);
159        }
160
161        // `kind_types`	1 byte	0x01	kind marker for types size section
162        let (input, kind_types) = consume_u8(input)?;
163        if kind_types != KIND_TYPES {
164            return Err(EofDecodeError::InvalidTypesKind);
165        }
166
167        // `types_size`	2 bytes	0x0004-0xFFFF
168        // 16-bit unsigned big-endian integer denoting the length of the type section content
169        let (input, types_size) = consume_u16(input)?;
170        header.types_size = types_size;
171
172        if header.types_size % 4 != 0 {
173            return Err(EofDecodeError::InvalidTypesSection);
174        }
175
176        // `kind_code`	1 byte	0x02	kind marker for code size section
177        let (input, kind_types) = consume_u8(input)?;
178        if kind_types != KIND_CODE {
179            return Err(EofDecodeError::InvalidCodeKind);
180        }
181
182        // `code_sections_sizes`
183        let (input, sizes, sum) = consume_header_section_size(input)?;
184
185        // more than 1024 code sections are not allowed
186        if sizes.len() > 0x0400 {
187            return Err(EofDecodeError::TooManyCodeSections);
188        }
189
190        if sizes.is_empty() {
191            return Err(EofDecodeError::ZeroCodeSections);
192        }
193
194        if sizes.len() != (types_size / 4) as usize {
195            return Err(EofDecodeError::MismatchCodeAndTypesSize);
196        }
197
198        header.code_sizes = sizes;
199        header.sum_code_sizes = sum;
200
201        let (input, kind_container_or_data) = consume_u8(input)?;
202
203        let input = match kind_container_or_data {
204            KIND_CONTAINER => {
205                // container_sections_sizes
206                let (input, sizes, sum) = consume_header_section_size(input)?;
207                // the number of container sections may not exceed 256
208                if sizes.len() > 0x0100 {
209                    return Err(EofDecodeError::TooManyContainerSections);
210                }
211                header.container_sizes = sizes;
212                header.sum_container_sizes = sum;
213                let (input, kind_data) = consume_u8(input)?;
214                if kind_data != KIND_DATA {
215                    return Err(EofDecodeError::InvalidDataKind);
216                }
217                input
218            }
219            KIND_DATA => input,
220            _ => return Err(EofDecodeError::InvalidKindAfterCode),
221        };
222
223        // `data_size`	2 bytes	0x0000-0xFFFF	16-bit
224        // unsigned big-endian integer denoting the length
225        // of the data section content (for not yet deployed
226        // containers this can be more than the actual content, see Data Section Lifecycle)
227        let (input, data_size) = consume_u16(input)?;
228        header.data_size = data_size;
229
230        // `terminator`	1 byte	0x00	marks the end of the EofHeader
231        let (input, terminator) = consume_u8(input)?;
232        if terminator != KIND_TERMINAL {
233            return Err(EofDecodeError::InvalidTerminalByte);
234        }
235
236        Ok((header, input))
237    }
238}
239
240#[cfg(test)]
241mod tests {
242    use super::*;
243    use primitives::hex;
244    use std::vec;
245
246    #[test]
247    fn sanity_header_decode() {
248        let input = hex!("ef000101000402000100010400000000800000fe");
249        let (header, _) = EofHeader::decode(&input).unwrap();
250        assert_eq!(header.types_size, 4);
251        assert_eq!(header.code_sizes, vec![1]);
252        assert_eq!(header.container_sizes, Vec::<u16>::new());
253        assert_eq!(header.data_size, 0);
254    }
255
256    #[test]
257    fn decode_header_not_terminated() {
258        let input = hex!("ef0001010004");
259        assert_eq!(EofHeader::decode(&input), Err(EofDecodeError::MissingInput));
260    }
261
262    #[test]
263    fn failing_test() {
264        let input = hex!("ef00010100040200010006030001001404000200008000016000e0000000ef000101000402000100010400000000800000fe");
265        let _ = EofHeader::decode(&input).unwrap();
266    }
267
268    #[test]
269    fn cut_header() {
270        let input = hex!("ef0001010000028000");
271        assert_eq!(
272            EofHeader::decode(&input),
273            Err(EofDecodeError::ShortInputForSizes)
274        );
275    }
276
277    #[test]
278    fn short_input() {
279        let input = hex!("ef0001010000028000");
280        assert_eq!(
281            EofHeader::decode(&input),
282            Err(EofDecodeError::ShortInputForSizes)
283        );
284    }
285}