@@ -2,7 +2,7 @@ use crate::{
2
2
primitives:: { B256 , U256 } ,
3
3
InstructionResult ,
4
4
} ;
5
- use core:: fmt;
5
+ use core:: { fmt, ptr } ;
6
6
use std:: vec:: Vec ;
7
7
8
8
/// EVM interpreter stack limit.
@@ -222,8 +222,14 @@ impl Stack {
222
222
}
223
223
224
224
/// Duplicates the `N`th value from the top of the stack.
225
+ ///
226
+ /// # Panics
227
+ ///
228
+ /// Panics if `n` is 0.
225
229
#[ inline]
230
+ #[ cfg_attr( debug_assertions, track_caller) ]
226
231
pub fn dup ( & mut self , n : usize ) -> Result < ( ) , InstructionResult > {
232
+ assume ! ( n > 0 , "attempted to dup 0" ) ;
227
233
let len = self . data . len ( ) ;
228
234
if len < n {
229
235
Err ( InstructionResult :: StackUnderflow )
@@ -232,16 +238,23 @@ impl Stack {
232
238
} else {
233
239
// SAFETY: check for out of bounds is done above and it makes this safe to do.
234
240
unsafe {
241
+ let ptr = self . data . as_mut_ptr ( ) . add ( len) ;
242
+ ptr:: copy_nonoverlapping ( ptr. sub ( n) , ptr, 1 ) ;
235
243
self . data . set_len ( len + 1 ) ;
236
244
}
237
- self . data [ len] = self . data [ len - n] ;
238
245
Ok ( ( ) )
239
246
}
240
247
}
241
248
242
249
/// Swaps the topmost value with the `N`th value from the top.
250
+ ///
251
+ /// # Panics
252
+ ///
253
+ /// Panics if `n` is 0.
243
254
#[ inline]
255
+ #[ cfg_attr( debug_assertions, track_caller) ]
244
256
pub fn swap ( & mut self , n : usize ) -> Result < ( ) , InstructionResult > {
257
+ assume ! ( n > 0 , "attempted to swap with 0" ) ;
245
258
let len = self . data . len ( ) ;
246
259
if n >= len {
247
260
return Err ( InstructionResult :: StackUnderflow ) ;
0 commit comments