revm_bytecode/eof/
header.rs1use super::{
2 decode_helpers::{consume_u16, consume_u8},
3 EofDecodeError,
4};
5use std::vec::Vec;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Ord, PartialOrd)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct EofHeader {
11 pub types_size: u16,
15 pub code_sizes: Vec<u16>,
19 pub container_sizes: Vec<u16>,
23 pub data_size: u16,
25 pub sum_code_sizes: usize,
27 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 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 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 pub fn size(&self) -> usize {
71 2 + 1 + 3 + 3 + 2 * self.code_sizes.len() + if self.container_sizes.is_empty() { 0 } else { 3 + 2 * self.container_sizes.len() } + 3 + 1 }
80
81 pub fn data_size_raw_i(&self) -> usize {
85 self.size() - 3
87 }
88
89 pub fn types_count(&self) -> usize {
91 self.types_size as usize / 4
92 }
93
94 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 pub fn eof_size(&self) -> usize {
106 self.size() + self.body_size()
107 }
108
109 pub fn encode(&self, buffer: &mut Vec<u8>) {
111 buffer.extend_from_slice(&0xEF00u16.to_be_bytes());
113 buffer.push(0x01);
115 buffer.push(KIND_TYPES);
117 buffer.extend_from_slice(&self.types_size.to_be_bytes());
119 buffer.push(KIND_CODE);
121 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 if self.container_sizes.is_empty() {
128 buffer.push(KIND_DATA);
129 } else {
130 buffer.push(KIND_CONTAINER);
131 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 buffer.push(KIND_DATA);
138 }
139 buffer.extend_from_slice(&self.data_size.to_be_bytes());
141 buffer.push(KIND_TERMINAL);
143 }
144
145 pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> {
147 let mut header = EofHeader::default();
148
149 let (input, kind) = consume_u16(input)?;
151 if kind != 0xEF00 {
152 return Err(EofDecodeError::InvalidEOFMagicNumber);
153 }
154
155 let (input, version) = consume_u8(input)?;
157 if version != 0x01 {
158 return Err(EofDecodeError::InvalidEOFVersion);
159 }
160
161 let (input, kind_types) = consume_u8(input)?;
163 if kind_types != KIND_TYPES {
164 return Err(EofDecodeError::InvalidTypesKind);
165 }
166
167 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 let (input, kind_types) = consume_u8(input)?;
178 if kind_types != KIND_CODE {
179 return Err(EofDecodeError::InvalidCodeKind);
180 }
181
182 let (input, sizes, sum) = consume_header_section_size(input)?;
184
185 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 let (input, sizes, sum) = consume_header_section_size(input)?;
207 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 let (input, data_size) = consume_u16(input)?;
228 header.data_size = data_size;
229
230 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}