revm_primitives/bytecode/eof/
header.rs
1use super::{
2 decode_helpers::{consume_u16, consume_u8},
3 EofDecodeError,
4};
5use std::vec::Vec;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct EofHeader {
11 pub types_size: u16,
14 pub code_sizes: Vec<u16>,
17 pub container_sizes: Vec<u16>,
20 pub data_size: u16,
22 pub sum_code_sizes: usize,
24 pub sum_container_sizes: usize,
26}
27
28const KIND_TERMINAL: u8 = 0;
29const KIND_TYPES: u8 = 1;
30const KIND_CODE: u8 = 2;
31const KIND_CONTAINER: u8 = 3;
32const KIND_DATA: u8 = 4;
33
34#[inline]
35fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec<u16>, usize), EofDecodeError> {
36 let (input, num_sections) = consume_u16(input)?;
39 if num_sections == 0 {
40 return Err(EofDecodeError::NonSizes);
41 }
42 let num_sections = num_sections as usize;
43 let byte_size = num_sections * 2;
44 if input.len() < byte_size {
45 return Err(EofDecodeError::ShortInputForSizes);
46 }
47 let mut sizes = Vec::with_capacity(num_sections);
48 let mut sum = 0;
49 for i in 0..num_sections {
50 let code_size = u16::from_be_bytes([input[i * 2], input[i * 2 + 1]]);
53 if code_size == 0 {
54 return Err(EofDecodeError::ZeroSize);
55 }
56 sum += code_size as usize;
57 sizes.push(code_size);
58 }
59
60 Ok((&input[byte_size..], sizes, sum))
61}
62
63impl EofHeader {
64 pub fn size(&self) -> usize {
68 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 }
77
78 pub fn data_size_raw_i(&self) -> usize {
81 self.size() - 3
83 }
84
85 pub fn types_count(&self) -> usize {
87 self.types_size as usize / 4
88 }
89
90 pub fn body_size(&self) -> usize {
92 self.types_size as usize
93 + self.sum_code_sizes
94 + self.sum_container_sizes
95 + self.data_size as usize
96 }
97
98 pub fn eof_size(&self) -> usize {
100 self.size() + self.body_size()
101 }
102
103 pub fn encode(&self, buffer: &mut Vec<u8>) {
105 buffer.extend_from_slice(&0xEF00u16.to_be_bytes());
107 buffer.push(0x01);
109 buffer.push(KIND_TYPES);
111 buffer.extend_from_slice(&self.types_size.to_be_bytes());
113 buffer.push(KIND_CODE);
115 buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes());
117 for size in &self.code_sizes {
118 buffer.extend_from_slice(&size.to_be_bytes());
119 }
120 if self.container_sizes.is_empty() {
122 buffer.push(KIND_DATA);
123 } else {
124 buffer.push(KIND_CONTAINER);
125 buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes());
127 for size in &self.container_sizes {
128 buffer.extend_from_slice(&size.to_be_bytes());
129 }
130 buffer.push(KIND_DATA);
132 }
133 buffer.extend_from_slice(&self.data_size.to_be_bytes());
135 buffer.push(KIND_TERMINAL);
137 }
138
139 pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> {
141 let mut header = EofHeader::default();
142
143 let (input, kind) = consume_u16(input)?;
145 if kind != 0xEF00 {
146 return Err(EofDecodeError::InvalidEOFMagicNumber);
147 }
148
149 let (input, version) = consume_u8(input)?;
151 if version != 0x01 {
152 return Err(EofDecodeError::InvalidEOFVersion);
153 }
154
155 let (input, kind_types) = consume_u8(input)?;
157 if kind_types != KIND_TYPES {
158 return Err(EofDecodeError::InvalidTypesKind);
159 }
160
161 let (input, types_size) = consume_u16(input)?;
164 header.types_size = types_size;
165
166 if header.types_size % 4 != 0 {
167 return Err(EofDecodeError::InvalidTypesSection);
168 }
169
170 let (input, kind_types) = consume_u8(input)?;
172 if kind_types != KIND_CODE {
173 return Err(EofDecodeError::InvalidCodeKind);
174 }
175
176 let (input, sizes, sum) = consume_header_section_size(input)?;
178
179 if sizes.len() > 0x0400 {
181 return Err(EofDecodeError::TooManyCodeSections);
182 }
183
184 if sizes.is_empty() {
185 return Err(EofDecodeError::ZeroCodeSections);
186 }
187
188 if sizes.len() != (types_size / 4) as usize {
189 return Err(EofDecodeError::MismatchCodeAndTypesSize);
190 }
191
192 header.code_sizes = sizes;
193 header.sum_code_sizes = sum;
194
195 let (input, kind_container_or_data) = consume_u8(input)?;
196
197 let input = match kind_container_or_data {
198 KIND_CONTAINER => {
199 let (input, sizes, sum) = consume_header_section_size(input)?;
201 if sizes.len() > 0x0100 {
203 return Err(EofDecodeError::TooManyContainerSections);
204 }
205 header.container_sizes = sizes;
206 header.sum_container_sizes = sum;
207 let (input, kind_data) = consume_u8(input)?;
208 if kind_data != KIND_DATA {
209 return Err(EofDecodeError::InvalidDataKind);
210 }
211 input
212 }
213 KIND_DATA => input,
214 _ => return Err(EofDecodeError::InvalidKindAfterCode),
215 };
216
217 let (input, data_size) = consume_u16(input)?;
222 header.data_size = data_size;
223
224 let (input, terminator) = consume_u8(input)?;
226 if terminator != KIND_TERMINAL {
227 return Err(EofDecodeError::InvalidTerminalByte);
228 }
229
230 Ok((header, input))
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237 use crate::hex;
238
239 #[test]
240 fn sanity_header_decode() {
241 let input = hex!("ef000101000402000100010400000000800000fe");
242 let (header, _) = EofHeader::decode(&input).unwrap();
243 assert_eq!(header.types_size, 4);
244 assert_eq!(header.code_sizes, vec![1]);
245 assert_eq!(header.container_sizes, Vec::<u16>::new());
246 assert_eq!(header.data_size, 0);
247 }
248
249 #[test]
250 fn decode_header_not_terminated() {
251 let input = hex!("ef0001010004");
252 assert_eq!(EofHeader::decode(&input), Err(EofDecodeError::MissingInput));
253 }
254
255 #[test]
256 fn failing_test() {
257 let input = hex!("ef00010100040200010006030001001404000200008000016000e0000000ef000101000402000100010400000000800000fe");
258 let _ = EofHeader::decode(&input).unwrap();
259 }
260
261 #[test]
262 fn cut_header() {
263 let input = hex!("ef0001010000028000");
264 assert_eq!(
265 EofHeader::decode(&input),
266 Err(EofDecodeError::ShortInputForSizes)
267 );
268 }
269
270 #[test]
271 fn short_input() {
272 let input = hex!("ef0001010000028000");
273 assert_eq!(
274 EofHeader::decode(&input),
275 Err(EofDecodeError::ShortInputForSizes)
276 );
277 }
278}