Skip to content

Commit 464bd61

Browse files
committed
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.
1 parent 3ffba41 commit 464bd61

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

.github/workflows/solana.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
run: cargo check --workspace --tests --manifest-path solana/Cargo.toml
7171

7272
- name: Run `cargo clippy`
73-
run: cargo clippy --workspace --tests --manifest-path solana/Cargo.toml
73+
run: cargo clippy --workspace --tests --manifest-path solana/Cargo.toml -- -Dclippy::cast_possible_truncation
7474

7575
- name: Cache solana tools
7676
id: cache-solana

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

+9
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ impl Bitmap {
3131
BM::<128>::from_value(self.map).get(index as usize)
3232
}
3333

34+
#[allow(clippy::cast_possible_truncation)]
3435
pub fn count_enabled_votes(&self, enabled: Bitmap) -> u8 {
3536
let bm = BM::<128>::from_value(self.map) & BM::<128>::from_value(enabled.map);
37+
// Conversion from usize to u8 is safe here. The Bitmap uses u128, so it's maximum length
38+
// (number of true bits) is 128.
3639
bm.len() as u8
3740
}
3841
}
@@ -64,4 +67,10 @@ mod tests {
6467
enabled.set(18, false);
6568
assert_eq!(bm.count_enabled_votes(enabled), 1);
6669
}
70+
71+
#[test]
72+
fn test_bitmap_len() {
73+
let max_bitmap = Bitmap::from_value(u128::MAX);
74+
assert_eq!(128, max_bitmap.count_enabled_votes(max_bitmap));
75+
}
6776
}

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ 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-
///
49+
// Truncation is allowed here. Clippy warns about the final returned expression, but it is
50+
// safe.
51+
#[allow(clippy::cast_possible_truncation)]
5052
pub fn capacity_at(&self, now: UnixTimestamp) -> u64 {
5153
assert!(self.last_tx_timestamp <= now);
5254

@@ -71,6 +73,10 @@ impl RateLimitState {
7173
+ time_passed as u128 * limit / (Self::RATE_LIMIT_DURATION as u128)
7274
};
7375

76+
// The use of `min` here prevents truncation.
77+
// The value of `limit` is u64 in reality. If both `calculated_capacity` and `limit` are at
78+
// their maxiumum possible values (u128::MAX and u64::MAX), then u64::MAX will be chosen by
79+
// `min`. So truncation is not possible.
7480
calculated_capacity.min(limit) as u64
7581
}
7682

0 commit comments

Comments
 (0)