Skip to content

Commit 9c040a2

Browse files
committed
solana: Configure additional security-relevant clippy lints
Adds a variety of clippy lints to enforce safe programming patterns Adds allow annotations for known-safe examples and explanations as to why they're OK Modifies some minor violations in the codebase
1 parent 3ffba41 commit 9c040a2

File tree

9 files changed

+62
-4
lines changed

9 files changed

+62
-4
lines changed

solana/Cargo.toml

+34
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,39 @@ members = [
55
]
66
resolver = "2"
77

8+
# Lints to improve security
9+
[workspace.lints.clippy]
10+
# The following rules should be enabled but conflict with other open PRs.
11+
# TODO enable the commented rules below
12+
# cast_possible_truncation = "deny"
13+
# cast_lossless= "deny"
14+
# as_conversions = "deny"
15+
# arithmetic_side_effects = "deny"
16+
# TODO: These rules should probably be enabled. Expect and unwrap are used in some traits and signal that something
17+
# has gone wrong with the program.
18+
# expect_used = "deny"
19+
# unwrap_used = "deny"
20+
integer_division = "deny"
21+
cast_possible_wrap = "deny"
22+
cast_precision_loss = "deny"
23+
cast_sign_loss = "deny"
24+
unchecked_duration_subtraction = "deny"
25+
overflow_check_conditional = "deny"
26+
modulo_one = "deny"
27+
manual_slice_size_calculation = "deny"
28+
large_stack_arrays = "deny"
29+
large_stack_frames = "deny"
30+
large_futures = "deny"
31+
recursive_format_impl = "deny"
32+
eq_op = "deny"
33+
lossy_float_literal = "deny"
34+
float_cmp = "deny"
35+
panic = "deny"
36+
todo = "deny"
37+
out_of_bounds_indexing = "deny"
38+
unreachable = "deny"
39+
cast_abs_to_unsigned = "deny"
40+
841
[workspace.dependencies]
942
wormhole-io = "0.1.3"
1043
wormhole-solana-utils = "0.2.0-alpha.15"
@@ -28,3 +61,4 @@ codegen-units = 1
2861
opt-level = 3
2962
incremental = false
3063
codegen-units = 1
64+

solana/modules/ntt-messages/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ wormhole = []
99
hash = [ "solana-program" ]
1010
anchor = [ "anchor-lang" ]
1111

12+
[lints]
13+
workspace = true
14+
1215
[dependencies]
1316
anchor-lang = { workspace = true, optional = true }
1417
wormhole-io.workspace = true

solana/modules/ntt-messages/src/trimmed_amount.rs

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ impl TrimmedAmount {
5050
}
5151
}
5252

53+
// Integer division is allowed here. The purpose of using it here is to remove the remainder so
54+
// there is no risk.
55+
#[allow(clippy::integer_division)]
5356
fn scale(amount: u64, from_decimals: u8, to_decimals: u8) -> u64 {
5457
if from_decimals == to_decimals {
5558
return amount;

solana/programs/example-native-token-transfers/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ solana-devnet = [ "wormhole-anchor-sdk/solana-devnet" ]
2626
tilt-devnet = [ "wormhole-anchor-sdk/tilt-devnet" ]
2727
tilt-devnet2 = [ "tilt-devnet" ]
2828

29+
[lints]
30+
workspace = true
31+
2932
[dependencies]
3033
ahash = "=0.8.5"
3134

solana/programs/example-native-token-transfers/src/instructions/transfer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl TransferArgs {
7474
amount.to_be_bytes().as_ref(),
7575
recipient_chain.id.to_be_bytes().as_ref(),
7676
recipient_address,
77-
&[*should_queue as u8],
77+
&[u8::from(*should_queue)],
7878
])
7979
}
8080
}

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ 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+
/// 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+
#[allow(clippy::integer_division)]
54+
#[allow(clippy::cast_sign_loss)]
5055
pub fn capacity_at(&self, now: UnixTimestamp) -> u64 {
5156
assert!(self.last_tx_timestamp <= now);
5257

53-
let limit = self.limit as u128;
58+
let limit = u128::from(self.limit);
5459

5560
// morally this is
5661
// capacity = old_capacity + (limit / rate_limit_duration) * time_passed
@@ -67,7 +72,7 @@ impl RateLimitState {
6772

6873
let calculated_capacity = {
6974
let time_passed = now - self.last_tx_timestamp;
70-
capacity_at_last_tx as u128
75+
u128::from(capacity_at_last_tx)
7176
+ time_passed as u128 * limit / (Self::RATE_LIMIT_DURATION as u128)
7277
};
7378

@@ -127,6 +132,7 @@ mod tests {
127132
use super::*;
128133

129134
#[test]
135+
#[allow(clippy::integer_division)]
130136
fn test_rate_limit() {
131137
let now = current_timestamp();
132138
let mut rate_limit_state = RateLimitState {

solana/programs/ntt-quoter/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ solana-devnet = []
1919
tilt-devnet = []
2020
tilt-devnet2 = ["tilt-devnet"]
2121

22+
[lints]
23+
workspace = true
24+
2225
[dependencies]
2326
anchor-lang = { workspace = true, features = ["init-if-needed"] }
2427
solana-program.workspace = true

solana/programs/ntt-quoter/src/processor/request_relay.rs

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ const GWEI: u64 = u64::pow(10, 9);
5858

5959
//TODO built-in u128 division likely still wastes a ton of compute units
6060
// might be more efficient to use f64 or ruint crate
61+
// SECURITY: Integer division is OK here. The calling code is responsible for understanding that
62+
// this function returns the quotient of the operation and that the remainder will be lost.
63+
#[allow(clippy::integer_division)]
6164
fn mul_div(scalar: u64, numerator: u64, denominator: u64) -> u64 {
6265
if scalar > 0 {
6366
//avoid potentially expensive u128 division

solana/programs/wormhole-governance/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ solana-devnet = [ "wormhole-anchor-sdk/solana-devnet" ]
2323
tilt-devnet = [ "wormhole-anchor-sdk/tilt-devnet" ]
2424
tilt-devnet2 = [ "tilt-devnet" ]
2525

26+
[lints]
27+
workspace = true
28+
2629
[dependencies]
2730
anchor-lang.workspace = true
2831
solana-program.workspace = true

0 commit comments

Comments
 (0)