Skip to content

Commit bd3a00b

Browse files
authored
feat: fix Uint<256> conversion issues by clamping values (#556)
* feat: fix `Uint<256>` conversion issues by clamping values * fix: clamp options * test: Add u256 overflow decompile tests
1 parent 6049181 commit bd3a00b

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

crates/core/tests/test_decompile.rs

+50
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,56 @@ mod integration_tests {
3838
}
3939
}
4040

41+
#[tokio::test]
42+
async fn test_decompile_u256_conversion_overflow_1() {
43+
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {
44+
println!("RPC_URL not set, skipping test");
45+
std::process::exit(0);
46+
});
47+
48+
let result = decompile(DecompilerArgs {
49+
target: String::from("0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"),
50+
rpc_url,
51+
default: true,
52+
skip_resolving: true,
53+
include_solidity: true,
54+
include_yul: false,
55+
output: String::from(""),
56+
name: String::from(""),
57+
timeout: 10000,
58+
abi: None,
59+
openai_api_key: String::from(""),
60+
llm_postprocess: false,
61+
})
62+
.await
63+
.expect("failed to decompile");
64+
}
65+
66+
#[tokio::test]
67+
async fn test_decompile_u256_conversion_overflow_2() {
68+
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {
69+
println!("RPC_URL not set, skipping test");
70+
std::process::exit(0);
71+
});
72+
73+
let result = decompile(DecompilerArgs {
74+
target: String::from("0x5141b82f5ffda4c6fe1e372978f1c5427640a190"),
75+
rpc_url,
76+
default: true,
77+
skip_resolving: true,
78+
include_solidity: true,
79+
include_yul: false,
80+
output: String::from(""),
81+
name: String::from(""),
82+
timeout: 10000,
83+
abi: None,
84+
openai_api_key: String::from(""),
85+
llm_postprocess: false,
86+
})
87+
.await
88+
.expect("failed to decompile");
89+
}
90+
4191
#[tokio::test]
4292
async fn test_decompile_weth() {
4393
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| {

crates/vm/src/core/vm.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ impl VM {
712712
let b = self.stack.pop()?;
713713

714714
// convert a to usize
715-
let usize_a: usize = a.value.try_into()?;
715+
let usize_a: usize = a.value.try_into().unwrap_or(usize::MAX);
716716

717717
let mut result = I256::ZERO;
718718
if !b.value.is_zero() {
@@ -737,8 +737,8 @@ impl VM {
737737
let size = self.stack.pop()?.value;
738738

739739
// Safely convert U256 to usize
740-
let offset: usize = offset.try_into()?;
741-
let size: usize = size.try_into()?;
740+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
741+
let size: usize = size.try_into().unwrap_or(usize::MAX);
742742

743743
let data = self.memory.read(offset, size);
744744
let result = keccak256(data);
@@ -802,9 +802,9 @@ impl VM {
802802
let i = self.stack.pop()?.value;
803803

804804
// Safely convert U256 to usize
805-
let i: usize = i.try_into()?;
805+
let i: usize = i.try_into().unwrap_or(usize::MAX);
806806

807-
let result = if i + 32 > self.calldata.len() {
807+
let result = if i.saturating_add(32) > self.calldata.len() {
808808
let mut value = [0u8; 32];
809809

810810
if i <= self.calldata.len() {
@@ -881,6 +881,7 @@ impl VM {
881881
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
882882
let size: usize = size.try_into().unwrap_or(usize::MAX);
883883

884+
// clamp values to bytecode length
884885
let value_offset_safe = offset.saturating_add(size).min(self.bytecode.len());
885886
let mut value =
886887
self.bytecode.get(offset..value_offset_safe).unwrap_or(&[]).to_owned();
@@ -932,8 +933,8 @@ impl VM {
932933
let size = self.stack.pop()?.value;
933934

934935
// Safely convert U256 to usize
935-
let dest_offset: usize = dest_offset.try_into()?;
936-
let size: usize = size.try_into()?;
936+
let dest_offset: usize = dest_offset.try_into().unwrap_or(0);
937+
let size: usize = size.try_into().unwrap_or(256);
937938

938939
let mut value = Vec::with_capacity(size);
939940
value.fill(0xff);
@@ -971,8 +972,8 @@ impl VM {
971972
let size = self.stack.pop()?.value;
972973

973974
// Safely convert U256 to usize
974-
let dest_offset: usize = dest_offset.try_into()?;
975-
let size: usize = size.try_into()?;
975+
let dest_offset: usize = dest_offset.try_into().unwrap_or(0);
976+
let size: usize = size.try_into().unwrap_or(256);
976977

977978
let mut value = Vec::with_capacity(size);
978979
value.fill(0xff);
@@ -1033,7 +1034,7 @@ impl VM {
10331034
// MLOAD
10341035
0x51 => {
10351036
let i = self.stack.pop()?.value;
1036-
let i: usize = i.try_into()?;
1037+
let i: usize = i.try_into().unwrap_or(usize::MAX);
10371038

10381039
let result = U256::from_be_slice(self.memory.read(i, 32).as_slice());
10391040

@@ -1050,7 +1051,7 @@ impl VM {
10501051
let value = self.stack.pop()?.value;
10511052

10521053
// Safely convert U256 to usize
1053-
let offset: usize = offset.try_into()?;
1054+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
10541055

10551056
// consume dynamic gas
10561057
let gas_cost = self.memory.expansion_cost(offset, 32);
@@ -1071,7 +1072,7 @@ impl VM {
10711072
let value = self.stack.pop()?.value;
10721073

10731074
// Safely convert U256 to usize
1074-
let offset: usize = offset.try_into()?;
1075+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
10751076

10761077
// consume dynamic gas
10771078
let gas_cost = self.memory.expansion_cost(offset, 1);
@@ -1289,8 +1290,8 @@ impl VM {
12891290
self.stack.pop_n(topic_count as usize).iter().map(|x| x.value).collect();
12901291

12911292
// Safely convert U256 to usize
1292-
let offset: usize = offset.try_into()?;
1293-
let size: usize = size.try_into()?;
1293+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
1294+
let size: usize = size.try_into().unwrap_or(usize::MAX);
12941295

12951296
let data = self.memory.read(offset, size);
12961297

@@ -1341,8 +1342,8 @@ impl VM {
13411342
let size = self.stack.pop()?.value;
13421343

13431344
// Safely convert U256 to usize
1344-
let offset: usize = offset.try_into()?;
1345-
let size: usize = size.try_into()?;
1345+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
1346+
let size: usize = size.try_into().unwrap_or(usize::MAX);
13461347

13471348
// consume dynamic gas
13481349
let gas_cost = self.memory.expansion_cost(offset, size);
@@ -1380,8 +1381,8 @@ impl VM {
13801381
let size = self.stack.pop()?.value;
13811382

13821383
// Safely convert U256 to usize
1383-
let offset: usize = offset.try_into()?;
1384-
let size: usize = size.try_into()?;
1384+
let offset: usize = offset.try_into().unwrap_or(usize::MAX);
1385+
let size: usize = size.try_into().unwrap_or(usize::MAX);
13851386

13861387
self.exit(1, self.memory.read(offset, size));
13871388
}

0 commit comments

Comments
 (0)