From 5d87f63ecab714b333e22deb34756aab520ea7c8 Mon Sep 17 00:00:00 2001 From: Jon-Becker Date: Thu, 30 Jan 2025 08:33:25 -0500 Subject: [PATCH 1/3] feat: fix `Uint<256>` conversion issues by clamping values --- crates/vm/src/core/vm.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/vm/src/core/vm.rs b/crates/vm/src/core/vm.rs index 16502219..b08d7544 100644 --- a/crates/vm/src/core/vm.rs +++ b/crates/vm/src/core/vm.rs @@ -712,7 +712,7 @@ impl VM { let b = self.stack.pop()?; // convert a to usize - let usize_a: usize = a.value.try_into()?; + let usize_a: usize = a.value.try_into().unwrap_or(usize::MAX); let mut result = I256::ZERO; if !b.value.is_zero() { @@ -737,8 +737,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let offset: usize = offset.try_into()?; - let size: usize = size.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); let data = self.memory.read(offset, size); let result = keccak256(data); @@ -802,7 +802,7 @@ impl VM { let i = self.stack.pop()?.value; // Safely convert U256 to usize - let i: usize = i.try_into()?; + let i: usize = i.try_into().unwrap_or(usize::MAX); let result = if i + 32 > self.calldata.len() { let mut value = [0u8; 32]; @@ -932,8 +932,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let dest_offset: usize = dest_offset.try_into()?; - let size: usize = size.try_into()?; + let dest_offset: usize = dest_offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); let mut value = Vec::with_capacity(size); value.fill(0xff); @@ -971,8 +971,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let dest_offset: usize = dest_offset.try_into()?; - let size: usize = size.try_into()?; + let dest_offset: usize = dest_offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); let mut value = Vec::with_capacity(size); value.fill(0xff); @@ -1033,7 +1033,7 @@ impl VM { // MLOAD 0x51 => { let i = self.stack.pop()?.value; - let i: usize = i.try_into()?; + let i: usize = i.try_into().unwrap_or(usize::MAX); let result = U256::from_be_slice(self.memory.read(i, 32).as_slice()); @@ -1050,7 +1050,7 @@ impl VM { let value = self.stack.pop()?.value; // Safely convert U256 to usize - let offset: usize = offset.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); // consume dynamic gas let gas_cost = self.memory.expansion_cost(offset, 32); @@ -1071,7 +1071,7 @@ impl VM { let value = self.stack.pop()?.value; // Safely convert U256 to usize - let offset: usize = offset.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); // consume dynamic gas let gas_cost = self.memory.expansion_cost(offset, 1); @@ -1289,8 +1289,8 @@ impl VM { self.stack.pop_n(topic_count as usize).iter().map(|x| x.value).collect(); // Safely convert U256 to usize - let offset: usize = offset.try_into()?; - let size: usize = size.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); let data = self.memory.read(offset, size); @@ -1341,8 +1341,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let offset: usize = offset.try_into()?; - let size: usize = size.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); // consume dynamic gas let gas_cost = self.memory.expansion_cost(offset, size); @@ -1380,8 +1380,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let offset: usize = offset.try_into()?; - let size: usize = size.try_into()?; + let offset: usize = offset.try_into().unwrap_or(usize::MAX); + let size: usize = size.try_into().unwrap_or(usize::MAX); self.exit(1, self.memory.read(offset, size)); } From 05653c7f676d5b90c2fd562419a197b447de111b Mon Sep 17 00:00:00 2001 From: Jon-Becker Date: Thu, 30 Jan 2025 10:47:47 -0500 Subject: [PATCH 2/3] fix: clamp options --- crates/vm/src/core/vm.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/vm/src/core/vm.rs b/crates/vm/src/core/vm.rs index b08d7544..f7bc6893 100644 --- a/crates/vm/src/core/vm.rs +++ b/crates/vm/src/core/vm.rs @@ -804,7 +804,7 @@ impl VM { // Safely convert U256 to usize let i: usize = i.try_into().unwrap_or(usize::MAX); - let result = if i + 32 > self.calldata.len() { + let result = if i.saturating_add(32) > self.calldata.len() { let mut value = [0u8; 32]; if i <= self.calldata.len() { @@ -881,6 +881,7 @@ impl VM { let offset: usize = offset.try_into().unwrap_or(usize::MAX); let size: usize = size.try_into().unwrap_or(usize::MAX); + // clamp values to bytecode length let value_offset_safe = offset.saturating_add(size).min(self.bytecode.len()); let mut value = self.bytecode.get(offset..value_offset_safe).unwrap_or(&[]).to_owned(); @@ -932,8 +933,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let dest_offset: usize = dest_offset.try_into().unwrap_or(usize::MAX); - let size: usize = size.try_into().unwrap_or(usize::MAX); + let dest_offset: usize = dest_offset.try_into().unwrap_or(0); + let size: usize = size.try_into().unwrap_or(256); let mut value = Vec::with_capacity(size); value.fill(0xff); @@ -971,8 +972,8 @@ impl VM { let size = self.stack.pop()?.value; // Safely convert U256 to usize - let dest_offset: usize = dest_offset.try_into().unwrap_or(usize::MAX); - let size: usize = size.try_into().unwrap_or(usize::MAX); + let dest_offset: usize = dest_offset.try_into().unwrap_or(0); + let size: usize = size.try_into().unwrap_or(256); let mut value = Vec::with_capacity(size); value.fill(0xff); From 220d20f8eb3f8a858e5f79281318459454dcd62c Mon Sep 17 00:00:00 2001 From: Jon-Becker Date: Thu, 30 Jan 2025 11:03:08 -0500 Subject: [PATCH 3/3] test: Add u256 overflow decompile tests --- crates/core/tests/test_decompile.rs | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/crates/core/tests/test_decompile.rs b/crates/core/tests/test_decompile.rs index ff5eaeb6..7d61b15b 100644 --- a/crates/core/tests/test_decompile.rs +++ b/crates/core/tests/test_decompile.rs @@ -38,6 +38,56 @@ mod integration_tests { } } + #[tokio::test] + async fn test_decompile_u256_conversion_overflow_1() { + let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| { + println!("RPC_URL not set, skipping test"); + std::process::exit(0); + }); + + let result = decompile(DecompilerArgs { + target: String::from("0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"), + rpc_url, + default: true, + skip_resolving: true, + include_solidity: true, + include_yul: false, + output: String::from(""), + name: String::from(""), + timeout: 10000, + abi: None, + openai_api_key: String::from(""), + llm_postprocess: false, + }) + .await + .expect("failed to decompile"); + } + + #[tokio::test] + async fn test_decompile_u256_conversion_overflow_2() { + let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| { + println!("RPC_URL not set, skipping test"); + std::process::exit(0); + }); + + let result = decompile(DecompilerArgs { + target: String::from("0x5141b82f5ffda4c6fe1e372978f1c5427640a190"), + rpc_url, + default: true, + skip_resolving: true, + include_solidity: true, + include_yul: false, + output: String::from(""), + name: String::from(""), + timeout: 10000, + abi: None, + openai_api_key: String::from(""), + llm_postprocess: false, + }) + .await + .expect("failed to decompile"); + } + #[tokio::test] async fn test_decompile_weth() { let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {