Skip to content

Commit 51130bc

Browse files
authored
solana: Configure clippy to deny possible truncation (#285)
* solana: Configure clippy to deny possible truncation Adds a clippy rule to block the inclusion of code that can result in truncation (i.e. `as T` conversions) Adds linting directive to existing instances in the code and add comments about why they are safe Add a unit test on bitmap length to confirm that the maximum possible number of votes (i.e. maximum "length" of the bitmap) is within the limits of u8. * solana: deny truncation in Cargo.toml instead of GitHub yml * solana: Remove TODO referencing old PRs * node: solana CI - fix Cargo.toml path * solana: Change "as" to try_from()
1 parent 9e9a386 commit 51130bc

File tree

5 files changed

+16
-10
lines changed

5 files changed

+16
-10
lines changed

.github/workflows/solana.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
run: cargo check --workspace --tests --manifest-path Cargo.toml
5151

5252
- name: Run `cargo clippy`
53-
run: cargo clippy --workspace --tests --manifest-path Cargo.toml
53+
run: cargo clippy --workspace --tests --manifest-path Cargo.toml -- -Dclippy::cast_possible_truncation
5454

5555
- name: Cache solana tools
5656
id: cache-solana

solana/Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ warnings = "deny"
1010

1111
# Lints to improve security
1212
[workspace.lints.clippy]
13-
# The following rules should be enabled but conflict with other open PRs.
1413
# TODO enable the commented rules below
15-
# cast_possible_truncation = "deny"
14+
cast_possible_truncation = "deny"
1615
# cast_lossless= "deny"
1716
# as_conversions = "deny"
1817
# arithmetic_side_effects = "deny"

solana/programs/example-native-token-transfers/src/bitmap.rs

-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ impl Bitmap {
4343

4444
pub fn count_enabled_votes(&self, enabled: Bitmap) -> u8 {
4545
let bm = BM::<128>::from_value(self.map) & BM::<128>::from_value(enabled.map);
46-
// Conversion from usize to u8 is safe here. The Bitmap uses u128, so its maximum length
47-
// (number of true bits) is 128.
4846
bm.len()
4947
.try_into()
5048
.expect("Bitmap length must not exceed the bounds of u8")

solana/programs/example-native-token-transfers/src/queue/rate_limit.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ impl RateLimitState {
4646
/// Returns the capacity of the rate limiter.
4747
/// On-chain programs and unit tests should always use [`capacity`].
4848
/// This function is useful in solana-program-test, where the clock sysvar
49-
/// SECURITY: Integer division is OK here. We are not that concerned with precision. Removing
50-
/// the remainder in this case is arguably more secure as it reduces the available capacity.
51-
/// SECURITY: Sign loss is OK here. It is a conversion performed on a timestamp that must always be
52-
/// positive.
49+
// SECURITY: Integer division is OK here. We are not that concerned with precision. Removing
50+
// the remainder in this case is arguably more secure as it reduces the available capacity.
51+
// SECURITY: Sign loss is OK here. It is a conversion performed on a timestamp that must always be
52+
// positive.
53+
// SECURITY: Truncation is allowed here. Clippy warns about the final returned expression, but it is
54+
// safe.
5355
#[allow(clippy::integer_division)]
5456
#[allow(clippy::cast_sign_loss)]
57+
#[allow(clippy::cast_possible_truncation)]
5558
pub fn capacity_at(&self, now: UnixTimestamp) -> u64 {
5659
assert!(self.last_tx_timestamp <= now);
5760

@@ -76,6 +79,10 @@ impl RateLimitState {
7679
+ time_passed as u128 * limit / (Self::RATE_LIMIT_DURATION as u128)
7780
};
7881

82+
// The use of `min` here prevents truncation.
83+
// The value of `limit` is u64 in reality. If both `calculated_capacity` and `limit` are at
84+
// their maxiumum possible values (u128::MAX and u64::MAX), then u64::MAX will be chosen by
85+
// `min`. So truncation is not possible.
7986
calculated_capacity.min(limit) as u64
8087
}
8188

solana/programs/wormhole-governance/src/instructions/governance.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ impl GovernanceMessage {
162162
acc.is_signer.write(writer)?;
163163
acc.is_writable.write(writer)?;
164164
}
165-
(data.len() as u16).write(writer)?;
165+
u16::try_from(data.len())
166+
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "data length overflow"))?
167+
.write(writer)?;
166168
writer.write_all(data)
167169
}
168170
}

0 commit comments

Comments
 (0)