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<u32>,
23 pub data_size: u16,
25 pub sum_code_sizes: usize,
27 pub sum_container_sizes: usize,
29}
30
31pub const KIND_TERMINAL: u8 = 0;
33pub const KIND_CODE_INFO: u8 = 1;
35pub const KIND_CODE: u8 = 2;
37pub const KIND_CONTAINER: u8 = 3;
39pub const KIND_DATA: u8 = 0xff;
41pub const CODE_SECTION_SIZE: usize = 2;
43pub const CONTAINER_SECTION_SIZE: usize = 4;
45
46#[inline]
50fn consume_header_code_section(input: &[u8]) -> Result<(&[u8], Vec<u16>, usize), EofDecodeError> {
51 let (input, num_sections) = consume_u16(input)?;
54 if num_sections == 0 {
55 return Err(EofDecodeError::NonSizes);
56 }
57 let num_sections = num_sections as usize;
58 let byte_size = num_sections * CODE_SECTION_SIZE;
59 if input.len() < byte_size {
60 return Err(EofDecodeError::ShortInputForSizes);
61 }
62 let mut sizes = Vec::with_capacity(num_sections);
63 let mut sum = 0;
64 for i in 0..num_sections {
65 let code_size = u16::from_be_bytes([
68 input[i * CODE_SECTION_SIZE],
69 input[i * CODE_SECTION_SIZE + 1],
70 ]);
71 if code_size == 0 {
72 return Err(EofDecodeError::ZeroSize);
73 }
74 sum += code_size as usize;
75 sizes.push(code_size);
76 }
77
78 Ok((&input[byte_size..], sizes, sum))
79}
80
81#[inline]
85fn consume_header_container_section(
86 input: &[u8],
87) -> Result<(&[u8], Vec<u32>, usize), EofDecodeError> {
88 let (input, num_sections) = consume_u16(input)?;
91 if num_sections == 0 {
92 return Err(EofDecodeError::NonSizes);
93 }
94 let num_sections = num_sections as usize;
95 let byte_size = num_sections * CONTAINER_SECTION_SIZE;
96 if input.len() < byte_size {
97 return Err(EofDecodeError::ShortInputForSizes);
98 }
99 let mut sizes = Vec::with_capacity(num_sections);
100 let mut sum = 0;
101 for i in 0..num_sections {
102 let container_size = u32::from_be_bytes(
105 input[i * CONTAINER_SECTION_SIZE..(i + 1) * CONTAINER_SECTION_SIZE]
106 .try_into()
107 .unwrap(),
108 );
109
110 if container_size == 0 {
111 return Err(EofDecodeError::ZeroSize);
112 }
113 sum += container_size as usize;
114 sizes.push(container_size);
115 }
116
117 Ok((&input[byte_size..], sizes, sum))
118}
119
120impl EofHeader {
121 pub fn size(&self) -> usize {
125 2 + 1 + 3 + 3 + CODE_SECTION_SIZE * self.code_sizes.len() + if self.container_sizes.is_empty() { 0 } else { 3 + CONTAINER_SECTION_SIZE * self.container_sizes.len() } + 3 + 1 }
134
135 pub fn data_size_raw_i(&self) -> usize {
139 self.size() - 3
141 }
142
143 pub fn types_count(&self) -> usize {
145 self.types_size as usize / 4
146 }
147
148 pub fn body_size(&self) -> usize {
152 self.types_size as usize
153 + self.sum_code_sizes
154 + self.sum_container_sizes
155 + self.data_size as usize
156 }
157
158 pub fn eof_size(&self) -> usize {
160 self.size() + self.body_size()
161 }
162
163 pub fn encode(&self, buffer: &mut Vec<u8>) {
165 buffer.extend_from_slice(&0xEF00u16.to_be_bytes());
167 buffer.push(0x01);
169 buffer.push(KIND_CODE_INFO);
171 buffer.extend_from_slice(&self.types_size.to_be_bytes());
173 buffer.push(KIND_CODE);
175 buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes());
177 for size in &self.code_sizes {
178 buffer.extend_from_slice(&size.to_be_bytes());
179 }
180 if !self.container_sizes.is_empty() {
182 buffer.push(KIND_CONTAINER);
183 buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes());
185 for size in &self.container_sizes {
186 buffer.extend_from_slice(&size.to_be_bytes());
187 }
188 }
189
190 buffer.push(KIND_DATA);
192 buffer.extend_from_slice(&self.data_size.to_be_bytes());
194 buffer.push(KIND_TERMINAL);
196 }
197
198 pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> {
202 let mut header = EofHeader::default();
203
204 let (input, kind) = consume_u16(input)?;
206 if kind != 0xEF00 {
207 return Err(EofDecodeError::InvalidEOFMagicNumber);
208 }
209
210 let (input, version) = consume_u8(input)?;
212 if version != 0x01 {
213 return Err(EofDecodeError::InvalidEOFVersion);
214 }
215
216 let (input, kind_code_info) = consume_u8(input)?;
218 if kind_code_info != KIND_CODE_INFO {
219 return Err(EofDecodeError::InvalidTypesKind);
220 }
221
222 let (input, types_size) = consume_u16(input)?;
225 header.types_size = types_size;
226
227 if header.types_size % CODE_SECTION_SIZE as u16 != 0 {
229 return Err(EofDecodeError::InvalidCodeInfo);
230 }
231
232 let (input, kind_code) = consume_u8(input)?;
234 if kind_code != KIND_CODE {
235 return Err(EofDecodeError::InvalidCodeKind);
236 }
237
238 let (input, sizes, sum) = consume_header_code_section(input)?;
240
241 if sizes.len() > 0x0400 {
243 return Err(EofDecodeError::TooManyCodeSections);
244 }
245
246 if sizes.is_empty() {
247 return Err(EofDecodeError::ZeroCodeSections);
248 }
249
250 if sizes.len() != (types_size / 4) as usize {
251 return Err(EofDecodeError::MismatchCodeAndInfoSize);
252 }
253
254 header.code_sizes = sizes;
255 header.sum_code_sizes = sum;
256
257 let (input, kind_container_or_data) = consume_u8(input)?;
258
259 let input = match kind_container_or_data {
260 KIND_CONTAINER => {
261 let (input, sizes, sum) = consume_header_container_section(input)?;
263 if sizes.len() > 0x0100 {
265 return Err(EofDecodeError::TooManyContainerSections);
266 }
267 header.container_sizes = sizes;
268 header.sum_container_sizes = sum;
269 let (input, kind_data) = consume_u8(input)?;
270 if kind_data != KIND_DATA {
271 return Err(EofDecodeError::InvalidDataKind);
272 }
273 input
274 }
275 KIND_DATA => input,
276 invalid_kind => return Err(EofDecodeError::InvalidKindAfterCode { invalid_kind }),
277 };
278
279 let (input, data_size) = consume_u16(input)?;
284 header.data_size = data_size;
285
286 let (input, terminator) = consume_u8(input)?;
288 if terminator != KIND_TERMINAL {
289 return Err(EofDecodeError::InvalidTerminalByte);
290 }
291
292 Ok((header, input))
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299 use primitives::hex;
300 use std::vec;
301
302 #[test]
303 fn sanity_header_decode() {
304 let input = hex!("ef00010100040200010001ff00000000800000fe");
305 let (header, _) = EofHeader::decode(&input).unwrap();
306 assert_eq!(header.types_size, 4);
307 assert_eq!(header.code_sizes, vec![1]);
308 assert_eq!(header.container_sizes, Vec::new());
309 assert_eq!(header.data_size, 0);
310 }
311
312 #[test]
313 fn decode_header_not_terminated() {
314 let input = hex!("ef0001010004");
315 assert_eq!(EofHeader::decode(&input), Err(EofDecodeError::MissingInput));
316 }
317
318 #[test]
319 fn failing_test() {
320 let input = hex!("ef0001010004020001000603000100000014ff000200008000016000e0000000ef000101000402000100010400000000800000fe");
321 let _ = EofHeader::decode(&input).unwrap();
322 }
323
324 #[test]
325 fn cut_header() {
326 let input = hex!("ef0001010000028000");
327 assert_eq!(
328 EofHeader::decode(&input),
329 Err(EofDecodeError::ShortInputForSizes)
330 );
331 }
332
333 #[test]
334 fn short_input() {
335 let input = hex!("ef0001010000028000");
336 assert_eq!(
337 EofHeader::decode(&input),
338 Err(EofDecodeError::ShortInputForSizes)
339 );
340 }
341}