revm_bytecode/legacy/
analyzed.rs1use super::JumpTable;
2use crate::opcode;
3use bitvec::{bitvec, order::Lsb0};
4use primitives::Bytes;
5use std::sync::Arc;
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33pub struct LegacyAnalyzedBytecode {
34 bytecode: Bytes,
36 original_len: usize,
38 jump_table: JumpTable,
40}
41
42impl Default for LegacyAnalyzedBytecode {
43 #[inline]
44 fn default() -> Self {
45 Self {
46 bytecode: Bytes::from_static(&[0]),
47 original_len: 0,
48 jump_table: JumpTable(Arc::new(bitvec![u8, Lsb0; 0])),
49 }
50 }
51}
52
53impl LegacyAnalyzedBytecode {
54 pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
62 if original_len > bytecode.len() {
63 panic!("original_len is greater than bytecode length");
64 }
65 if original_len > jump_table.0.len() {
66 panic!(
67 "jump table length {} is less than original length {}",
68 jump_table.0.len(),
69 original_len
70 );
71 }
72
73 if bytecode.is_empty() {
74 panic!("bytecode cannot be empty");
75 }
76
77 if bytecode.last() != Some(&opcode::STOP) {
78 panic!("last bytecode byte should be STOP (0x00)");
79 }
80
81 Self {
82 bytecode,
83 original_len,
84 jump_table,
85 }
86 }
87
88 pub fn bytecode(&self) -> &Bytes {
92 &self.bytecode
93 }
94
95 pub fn original_len(&self) -> usize {
97 self.original_len
98 }
99
100 pub fn original_bytes(&self) -> Bytes {
102 self.bytecode.slice(..self.original_len)
103 }
104
105 pub fn original_byte_slice(&self) -> &[u8] {
107 &self.bytecode[..self.original_len]
108 }
109
110 pub fn jump_table(&self) -> &JumpTable {
112 &self.jump_table
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use crate::{opcode, LegacyRawBytecode};
119
120 use super::*;
121
122 #[test]
123 fn test_bytecode_new() {
124 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
125 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
126 let _ = LegacyAnalyzedBytecode::new(
127 bytecode.bytecode,
128 bytecode.original_len,
129 bytecode.jump_table,
130 );
131 }
132
133 #[test]
134 #[should_panic(expected = "original_len is greater than bytecode length")]
135 fn test_panic_on_large_original_len() {
136 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
137 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
138 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, 100, bytecode.jump_table);
139 }
140
141 #[test]
142 #[should_panic(expected = "jump table length 1 is less than original length 2")]
143 fn test_panic_on_short_jump_table() {
144 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
145 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
146 let jump_table = JumpTable(Arc::new(bitvec![u8, Lsb0; 0; 1]));
147 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, bytecode.original_len, jump_table);
148 }
149
150 #[test]
151 #[should_panic(expected = "last bytecode byte should be STOP (0x00)")]
152 fn test_panic_on_non_stop_bytecode() {
153 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
154 let jump_table = JumpTable(Arc::new(bitvec![u8, Lsb0; 0; 2]));
155 let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table);
156 }
157
158 #[test]
159 #[should_panic(expected = "bytecode cannot be empty")]
160 fn test_panic_on_empty_bytecode() {
161 let bytecode = Bytes::from_static(&[]);
162 let jump_table = JumpTable(Arc::new(bitvec![u8, Lsb0; 0; 0]));
163 let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table);
164 }
165}