Skip to content

Commit

Permalink
Handle case when bytecode is empty (#275)
Browse files Browse the repository at this point in the history
## Type of change

<!--Delete points that do not apply-->

- Bug fix

## Changes

The following changes have been made:

- `_compute_bytecode_root()` now reverts when the `bytecode` argument is
an empty slice. Previously the function would enter an infinite loop.

## Notes

- This was reported as part of the attackathon

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
- [x] I have updated the changelog to reflect the changes on this PR.
  • Loading branch information
bitzoic authored Aug 1, 2024
1 parent 3a8a5dc commit dbd5e36
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Description of the upcoming release here.
- [#272](https://github.com/FuelLabs/sway-libs/pull/272) Fixes `From` implementations for Signed Integers with `TryFrom`.
- [#273](https://github.com/FuelLabs/sway-libs/pull/273) Fixes negative from implementations for Signed Integers.
- [#274](https://github.com/FuelLabs/sway-libs/pull/274) Fixes the `swap_configurables()` function to correctly handle the case where the bytecode is too large to fit in the buffer.
- [#275](https://github.com/FuelLabs/sway-libs/pull/275) Fixes an infinite loop in the Bytecode root library's `_compute_bytecode_root()` function.

#### Breaking

Expand Down
21 changes: 21 additions & 0 deletions libs/src/bytecode.sw
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ use ::bytecode::utils::{_compute_bytecode_root, _predicate_address_from_root, _s
///
/// * [b256] - The bytecode root of the contract or predicate.
///
/// # Reverts
///
/// * When the bytecode is empty.
///
/// # Examples
///
/// ```sway
Expand All @@ -41,6 +45,10 @@ pub fn compute_bytecode_root(bytecode: Vec<u8>) -> b256 {
///
/// * [b256] - The bytecode root of the contract or predicate.
///
/// # Reverts
///
/// * When the bytecode is empty.
///
/// # Examples
///
/// ```sway
Expand Down Expand Up @@ -71,6 +79,11 @@ pub fn compute_bytecode_root_with_configurables(
///
/// * [Address] - The address of the predicate.
///
///
/// # Reverts
///
/// * When the bytecode is empty.
///
/// # Examples
///
/// ```sway
Expand All @@ -97,6 +110,10 @@ pub fn compute_predicate_address(bytecode: Vec<u8>) -> Address {
///
/// * [Address] - The address of the predicate.
///
/// # Reverts
///
/// * When the bytecode is empty.
///
/// # Examples
///
/// ```sway
Expand Down Expand Up @@ -182,6 +199,7 @@ pub fn swap_configurables(
///
/// # Reverts
///
/// * When the bytecode is empty.
/// * When the contract's bytecode root does not match the passed bytecode.
///
/// # Examples
Expand Down Expand Up @@ -211,6 +229,7 @@ pub fn verify_contract_bytecode(contract_id: ContractId, bytecode: Vec<u8>) {
///
/// # Reverts
///
/// * When the bytecode is empty.
/// * When the contract's bytecode root does not match the passed bytecode.
///
/// # Examples
Expand Down Expand Up @@ -246,6 +265,7 @@ pub fn verify_contract_bytecode_with_configurables(
///
/// # Reverts
///
/// * When the bytecode is empty.
/// * When the predicate's address does not match the passed address.
///
/// # Examples
Expand Down Expand Up @@ -275,6 +295,7 @@ pub fn verify_predicate_address(predicate_id: Address, bytecode: Vec<u8>) {
///
/// # Reverts
///
/// * When the bytecode is empty.
/// * When the predicate's address does not match the passed address.
///
/// # Examples
Expand Down
1 change: 1 addition & 0 deletions libs/src/bytecode/utils.sw
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ fn _generate_leaves(bytecode: raw_slice) -> raw_slice {

/// Takes some bytecode and computes the bytecode root.
pub fn _compute_bytecode_root(bytecode: raw_slice) -> b256 {
assert(bytecode.number_of_bytes() != 0);
let mut vec_digest = _generate_leaves(bytecode);
let vec_digest_len = vec_digest.len::<b256>();
let mut size = (vec_digest_len + 1) >> 1;
Expand Down
17 changes: 17 additions & 0 deletions tests/src/bytecode/tests/functions/compute_bytecode_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,20 @@ mod success {
assert_eq!(result_bytecode_root, predicate_bytecode_root);
}
}

mod revert {

use super::*;

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, _wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();

// Call the contract and compute the bytecode root
let _result_bytecode_root =
compute_bytecode_root(&test_contract_instance, empty_bytecode).await;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,25 @@ mod success {
assert_eq!(result_bytecode_root, predicate_bytecode_root);
}
}

mod revert {

use super::*;

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, _wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();
let my_configurables: Vec<(u64, Vec<u8>)> = Vec::new();

// Call the contract and compute the bytecode root
let _result_bytecode_root = compute_bytecode_root_with_configurables(
&test_contract_instance,
empty_bytecode,
my_configurables,
)
.await;
}
}
17 changes: 17 additions & 0 deletions tests/src/bytecode/tests/functions/compute_predicate_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,20 @@ mod success {
assert_eq!(result_address, predicate_instance.address().into());
}
}

mod revert {

use super::*;

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, _wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();

// Call the contract and compute the address
let _result_address =
compute_predicate_address(&test_contract_instance, empty_bytecode).await;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,25 @@ mod success {
assert_eq!(result_address, predicate_instance.address().into());
}
}

mod revert {

use super::*;

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();
let my_configurables: Vec<(u64, Vec<u8>)> = Vec::new();

// Call the contract and compute the address
let _result_address = compute_predicate_address_with_configurables(
&test_contract_instance,
empty_bytecode,
my_configurables,
)
.await;
}
}
19 changes: 19 additions & 0 deletions tests/src/bytecode/tests/functions/verify_contract_bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,23 @@ mod revert {
)
.await;
}

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();

// Deploy the new simple contract with the bytecode that contains the changes
let (simple_contract_instance, id) = deploy_simple_contract_from_file(wallet.clone()).await;

verify_simple_contract_bytecode(
&test_contract_instance,
empty_bytecode,
id,
simple_contract_instance,
)
.await;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,27 @@ mod revert {
)
.await;
}

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();
let my_configurables: Vec<(u64, Vec<u8>)> = Vec::new();

// Deploy the new simple contract with the bytecode that contains the changes
let (simple_contract_instance, id) =
deploy_simple_contract_with_configurables_from_file(wallet.clone(), 0).await;

// Call the contract and compute the bytecode root
verify_simple_contract_bytecode_with_configurables(
&test_contract_instance,
empty_bytecode,
my_configurables,
id,
simple_contract_instance,
)
.await;
}
}
18 changes: 18 additions & 0 deletions tests/src/bytecode/tests/functions/verify_predicate_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,22 @@ mod revert {
)
.await;
}

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();

// Create an instance of the predicate
let predicate_instance = setup_predicate_from_file(wallet.clone()).await;

verify_predicate_address(
&test_contract_instance,
empty_bytecode,
predicate_instance.address().into(),
)
.await;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,25 @@ mod revert {
)
.await;
}

#[tokio::test]
#[should_panic]
async fn when_bytecode_is_empty() {
let (test_contract_instance, wallet) = test_contract_instance().await;

let empty_bytecode: Vec<u8> = Vec::new();
let my_configurables: Vec<(u64, Vec<u8>)> = Vec::new();

// Create an instance of the predicate
let predicate_instance =
setup_predicate_from_file_with_configurable(wallet.clone(), 0).await;

verify_predicate_address_with_configurables(
&test_contract_instance,
empty_bytecode,
my_configurables,
predicate_instance.address().into(),
)
.await;
}
}

0 comments on commit dbd5e36

Please sign in to comment.