Skip to content

Commit 2a61bb2

Browse files
oslfmtsmoelius
authored andcommitted
add readme to declare lint macro
1 parent 765fdfb commit 2a61bb2

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

lints/type_cosplay/src/lib.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,37 @@ use solana_lints::{paths, utils::visit_expr_no_bodies};
1919
use if_chain::if_chain;
2020

2121
dylint_linting::impl_late_lint! {
22-
/// **What it does:**
23-
///
24-
/// **Why is this bad?**
25-
///
26-
/// **Known problems:** When only one enum is serialized, may miss certain edge cases.
22+
/// **What it does:** Checks that all deserialized types have a proper discriminant so that
23+
/// all types are guaranteed to deserialize differently.
24+
25+
/// Instead of searching for equivalent types and checking to make sure those specific
26+
/// types have a discriminant, this lint takes a more strict approach and instead enforces
27+
/// all deserialized types it collects, to have a discriminant, regardless of whether the
28+
/// types are equivalent or not.
29+
30+
/// We define a proper discriminant as an enum with as many variants as there are struct
31+
/// types in the program. Further, the discriminant should be the first field of every
32+
/// struct in order to avoid overwrite by arbitrary length fields, like vectors.
33+
34+
/// A second case of a proper discriminant is when a single enum contains as variants all the struct
35+
/// types that will be deserialized. This "umbrella" enum essentially has a built-in
36+
/// discriminant. If it is the only type that is deserialized, then all struct types
37+
/// are guaranteed to be unique since the program will have to match a specific variant.
2738
///
28-
/// **Example:**
39+
/// **Why is this bad?**
40+
/// The type cosplay issue is when one account type can be substituted for another account type.
41+
/// This occurs when a type deserializes exactly the same as another type, such that you can't
42+
/// tell the difference between deserialized type `X` and deserialized type `Y`. This allows a
43+
/// malicious user to substitute `X` for `Y` or vice versa, and the code may perform unauthorized
44+
/// actions with the bytes.
2945
///
30-
/// ```rust
31-
/// // example code where a warning is issued
32-
/// ```
33-
/// Use instead:
34-
/// ```rust
35-
/// // example code that does not raise a warning
36-
/// ```
46+
/// **Known problems:** In the case when only one enum is deserialized, this lint by default
47+
/// regards that as secure. However, this is not always the case. For example, if the program
48+
/// defines another enum and serializes, but never deserializes it, a user could create this enum,
49+
/// and, if it deserializes the same as the first enum, then this may be a possible vulnerability.
50+
51+
/// Furthermore, one may have alternative definitions of a discriminant, such as using a bool,
52+
/// or u8, and not an enum. This will flag a false positive.
3753
pub TYPE_COSPLAY,
3854
Warn,
3955
"type is equivalent to another type",

lints/type_cosplay/ui/secure-2/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ pub mod type_cosplay_secure {
2323
}
2424
msg!("GM {}", user.authority);
2525
Ok(())
26-
},
26+
}
2727
AccountDiscriminant::Metadata(metadata) => {
2828
if ctx.accounts.user.owner != ctx.program_id {
2929
return Err(ProgramError::IllegalOwner);
3030
}
3131
msg!("GM {}", metadata.account);
3232
Ok(())
33-
},
33+
}
3434
}
35-
3635
}
3736
}
3837

0 commit comments

Comments
 (0)