Skip to content

Commit 86996a6

Browse files
GnomedDevmkrasnitski
authored andcommitted
Get rid of unsafe (#2686)
A discord bot library should not be using the tools reserved for low level OS interaction/data structure libraries.
1 parent c67cb81 commit 86996a6

File tree

6 files changed

+77
-34
lines changed

6 files changed

+77
-34
lines changed

CONTRIBUTING.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,9 @@ your code.
6363

6464
## Unsafe
6565

66-
Code that defines or uses `unsafe` functions must be reasoned with comments.
67-
`unsafe` code can pose a potential for undefined behaviour related bugs and other
68-
kinds of bugs to sprout if misused, weakening security. If you commit code containing
69-
`unsafe`, you should confirm that its usage is necessary and correct.
66+
Unsafe code is forbidden, and safe alternatives must be found. This can be mitigated by using
67+
a third party crate to offload the burden of justifying the unsafe code, or finding a safe
68+
alternative.
7069

7170
# Comment / Documentation style
7271

command_attr/src/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl LitExt for Lit {
1919
fn to_str(&self) -> String {
2020
match self {
2121
Self::Str(s) => s.value(),
22-
Self::ByteStr(s) => unsafe { String::from_utf8_unchecked(s.value()) },
22+
Self::ByteStr(s) => String::from_utf8_lossy(&s.value()).into_owned(),
2323
Self::Char(c) => c.value().to_string(),
2424
Self::Byte(b) => (b.value() as char).to_string(),
2525
_ => panic!("values must be a (byte)string or a char"),

src/http/routing.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::model::id::*;
66

77
/// Used to group requests together for ratelimiting.
88
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9-
pub struct RatelimitingBucket(Option<(std::mem::Discriminant<Route<'static>>, Option<NonZeroU64>)>);
9+
pub struct RatelimitingBucket(Option<(RouteKind, Option<NonZeroU64>)>);
1010

1111
impl RatelimitingBucket {
1212
#[must_use]
@@ -41,7 +41,20 @@ macro_rules! routes {
4141
)+
4242
}
4343

44+
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
45+
enum RouteKind {
46+
$($name,)+
47+
}
48+
4449
impl<$lt> Route<$lt> {
50+
fn kind(&self) -> RouteKind {
51+
match self {
52+
$(
53+
Self::$name {..} => RouteKind::$name,
54+
)+
55+
}
56+
}
57+
4558
#[must_use]
4659
pub fn path(self) -> Cow<'static, str> {
4760
match self {
@@ -60,20 +73,12 @@ macro_rules! routes {
6073
)+
6174
};
6275

63-
// This avoids adding a lifetime on RatelimitingBucket and causing lifetime infection
64-
// SAFETY: std::mem::discriminant erases lifetimes.
65-
let discriminant = unsafe {
66-
std::mem::transmute::<Discriminant<Route<'a>>, Discriminant<Route<'static>>>(
67-
std::mem::discriminant(self),
68-
)
69-
};
70-
7176
RatelimitingBucket(ratelimiting_kind.map(|r| {
7277
let id = match r {
7378
RatelimitingKind::PathAndId(id) => Some(id),
7479
RatelimitingKind::Path => None,
7580
};
76-
(discriminant, id)
81+
(self.kind(), id)
7782
}))
7883
}
7984

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
//! [gateway docs]: crate::gateway
5151
#![doc(html_root_url = "https://docs.rs/serenity/*")]
5252
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
53+
#![forbid(unsafe_code)]
5354
#![warn(
5455
unused,
5556
rust_2018_idioms,

src/model/guild/audit_log/mod.rs

+56-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Audit log types for administrative actions within guilds.
22
3-
use std::mem::transmute;
4-
53
use nonmax::{NonMaxU32, NonMaxU64};
64
use serde::ser::{Serialize, Serializer};
75

@@ -71,22 +69,62 @@ impl Action {
7169
pub fn from_value(value: u8) -> Action {
7270
match value {
7371
1 => Action::GuildUpdate,
74-
10..=12 => Action::Channel(unsafe { transmute(value) }),
75-
13..=15 => Action::ChannelOverwrite(unsafe { transmute(value) }),
76-
20..=28 => Action::Member(unsafe { transmute(value) }),
77-
30..=32 => Action::Role(unsafe { transmute(value) }),
78-
40..=42 => Action::Invite(unsafe { transmute(value) }),
79-
50..=52 => Action::Webhook(unsafe { transmute(value) }),
80-
60..=62 => Action::Emoji(unsafe { transmute(value) }),
81-
72..=75 => Action::Message(unsafe { transmute(value) }),
82-
80..=82 => Action::Integration(unsafe { transmute(value) }),
83-
83..=85 => Action::StageInstance(unsafe { transmute(value) }),
84-
90..=92 => Action::Sticker(unsafe { transmute(value) }),
85-
100..=102 => Action::ScheduledEvent(unsafe { transmute(value) }),
86-
110..=112 => Action::Thread(unsafe { transmute(value) }),
87-
140..=145 => Action::AutoMod(unsafe { transmute(value) }),
88-
150..=151 => Action::CreatorMonetization(unsafe { transmute(value) }),
89-
192..=193 => Action::VoiceChannelStatus(unsafe { transmute(value) }),
72+
10 => Action::Channel(ChannelAction::Create),
73+
11 => Action::Channel(ChannelAction::Update),
74+
12 => Action::Channel(ChannelAction::Delete),
75+
13 => Action::ChannelOverwrite(ChannelOverwriteAction::Create),
76+
14 => Action::ChannelOverwrite(ChannelOverwriteAction::Update),
77+
15 => Action::ChannelOverwrite(ChannelOverwriteAction::Delete),
78+
20 => Action::Member(MemberAction::Kick),
79+
21 => Action::Member(MemberAction::Prune),
80+
22 => Action::Member(MemberAction::BanAdd),
81+
23 => Action::Member(MemberAction::BanRemove),
82+
24 => Action::Member(MemberAction::Update),
83+
25 => Action::Member(MemberAction::RoleUpdate),
84+
26 => Action::Member(MemberAction::MemberMove),
85+
27 => Action::Member(MemberAction::MemberDisconnect),
86+
28 => Action::Member(MemberAction::BotAdd),
87+
30 => Action::Role(RoleAction::Create),
88+
31 => Action::Role(RoleAction::Update),
89+
32 => Action::Role(RoleAction::Delete),
90+
40 => Action::Invite(InviteAction::Create),
91+
41 => Action::Invite(InviteAction::Update),
92+
42 => Action::Invite(InviteAction::Delete),
93+
50 => Action::Webhook(WebhookAction::Create),
94+
51 => Action::Webhook(WebhookAction::Update),
95+
52 => Action::Webhook(WebhookAction::Delete),
96+
60 => Action::Emoji(EmojiAction::Create),
97+
61 => Action::Emoji(EmojiAction::Update),
98+
62 => Action::Emoji(EmojiAction::Delete),
99+
72 => Action::Message(MessageAction::Delete),
100+
73 => Action::Message(MessageAction::BulkDelete),
101+
74 => Action::Message(MessageAction::Pin),
102+
75 => Action::Message(MessageAction::Unpin),
103+
80 => Action::Integration(IntegrationAction::Create),
104+
81 => Action::Integration(IntegrationAction::Update),
105+
82 => Action::Integration(IntegrationAction::Delete),
106+
83 => Action::StageInstance(StageInstanceAction::Create),
107+
84 => Action::StageInstance(StageInstanceAction::Update),
108+
85 => Action::StageInstance(StageInstanceAction::Delete),
109+
90 => Action::Sticker(StickerAction::Create),
110+
91 => Action::Sticker(StickerAction::Update),
111+
92 => Action::Sticker(StickerAction::Delete),
112+
100 => Action::ScheduledEvent(ScheduledEventAction::Create),
113+
101 => Action::ScheduledEvent(ScheduledEventAction::Update),
114+
102 => Action::ScheduledEvent(ScheduledEventAction::Delete),
115+
110 => Action::Thread(ThreadAction::Create),
116+
111 => Action::Thread(ThreadAction::Update),
117+
112 => Action::Thread(ThreadAction::Delete),
118+
140 => Action::AutoMod(AutoModAction::RuleCreate),
119+
141 => Action::AutoMod(AutoModAction::RuleUpdate),
120+
142 => Action::AutoMod(AutoModAction::RuleDelete),
121+
143 => Action::AutoMod(AutoModAction::BlockMessage),
122+
144 => Action::AutoMod(AutoModAction::FlagToChannel),
123+
145 => Action::AutoMod(AutoModAction::UserCommunicationDisabled),
124+
150 => Action::CreatorMonetization(CreatorMonetizationAction::RequestCreated),
125+
151 => Action::CreatorMonetization(CreatorMonetizationAction::TermsAccepted),
126+
192 => Action::VoiceChannelStatus(VoiceChannelStatusAction::StatusUpdate),
127+
193 => Action::VoiceChannelStatus(VoiceChannelStatusAction::StatusDelete),
90128
_ => Action::Unknown(value),
91129
}
92130
}

src/model/id.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ macro_rules! id_u64 {
111111

112112
impl From<$name> for NonZeroI64 {
113113
fn from(id: $name) -> NonZeroI64 {
114-
unsafe {NonZeroI64::new_unchecked(id.get() as i64)}
114+
NonZeroI64::new(id.get() as i64).unwrap()
115115
}
116116
}
117117

0 commit comments

Comments
 (0)