Attackathon _ Fuel Network 33193 - [Blockchain_DLT - Medium] Fuel SDKs ABI Decoder Behaves Different
Submitted on Sat Jul 13 2024 21:25:36 GMT-0400 (Atlantic Standard Time) by @savi0ur for Attackathon | Fuel Network
Report ID: #33193
Report type: Blockchain/DLT
Report severity: Medium
Target: https://github.com/fuellabs/fuels-rs/tree/d3ac1d3f8910cc12c662ccbe5ff51d9e9354ed1a
Impacts:
A bug in the respective layer 0/1/2 network code that results in unintended smart contract behavior with no concrete funds at direct risk
Description
Bug Description
Inside fuels-rs
module, we have fuels-core
module which defines a functionality to ABI encode and decode.
https://github.com/FuelLabs/fuels-rs/blob/d3ac1d3f8910cc12c662ccbe5ff51d9e9354ed1a/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs#L336-L342
While decoding data, it first finds the length of that data by reading first 8 bytes using peek_length
function. This 8 byte data is converted to usize
. Since the size of usize
is platform dependent, this conversion behaves differently based on the platform architecture on which this code runs.
For example, When run on 64 bit machine, where usize
is 64 bit wide, if length of data (bytes argument
) is > u32::MAX
, it will correctly returns length of the data by converting this length to usize
using try_into
function. Since usize
is 64 bit wide, it will be able to store this result.
But when run on 32-bit machine, where usize
is 32 bit wide, if length of data is > u32::MAX
, peek_length
function will revert with error - "could not convert u64 to usize"
As we have seen, based on the platform architecture, this function behaves differently.
Impact
Fuels SDK's ABI encoding and decoding behaves differently based on architecture of the system.
Recommendation
Avoid conversions that may behave differently across architectures. Use architecture independent data types for performing required operations.
References
https://github.com/FuelLabs/fuels-rs/blob/d3ac1d3f8910cc12c662ccbe5ff51d9e9354ed1a/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs#L336-L342
Proof of concept
Proof Of Concept
peek_length
function is called by every decode_XXX
function in bounded_decoder.rs
. We have used ParamType::String
to show an issue using decode_std_string(bytes)
function.
Steps to Run using Foundry:
Change directory to
fuels-rs
directory i.e.,cd fuels-rs
Copy following test case in
packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs
Open terminal and run
cargo test --package fuels-core --lib -- codec::abi_decoder::decode_as_debug_str::tests::test_param_type_decode_bug_diff_arch --exact --show-output
Console Output:
On 64-bit machine, this test case will execute successfully.
On 32-bit machine, this test case will fail.
Last updated