diff options
| author | Maiddog <[email protected]> | 2017-08-27 04:17:59 -0500 |
|---|---|---|
| committer | alex <[email protected]> | 2017-08-27 11:17:59 +0200 |
| commit | e1a8fe3e9f619fbb94dd54993c8f5d25fd5dc375 (patch) | |
| tree | 4c6c45cc592505f971c13aee8dfbdd41107a84ce /src | |
| parent | Add ability to play DCA and Opus files. (#148) (diff) | |
| download | serenity-e1a8fe3e9f619fbb94dd54993c8f5d25fd5dc375.tar.xz serenity-e1a8fe3e9f619fbb94dd54993c8f5d25fd5dc375.zip | |
Prevent malformed opus data from crashing the bot process (#149)
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/context.rs | 36 | ||||
| -rw-r--r-- | src/client/dispatch.rs | 124 | ||||
| -rw-r--r-- | src/gateway/shard.rs | 72 | ||||
| -rw-r--r-- | src/model/channel/reaction.rs | 53 | ||||
| -rw-r--r-- | src/model/user.rs | 61 | ||||
| -rw-r--r-- | src/voice/streamer.rs | 5 |
6 files changed, 186 insertions, 165 deletions
diff --git a/src/client/context.rs b/src/client/context.rs index d0600b6..1bd5ed7 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -78,23 +78,25 @@ impl Context { pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> { let mut map = Map::new(); - feature_cache! {{ - let cache = CACHE.read().unwrap(); - - map.insert("username".to_owned(), Value::String(cache.user.name.clone())); - - if let Some(email) = cache.user.email.as_ref() { - map.insert("email".to_owned(), Value::String(email.clone())); - } - } else { - let user = http::get_current_user()?; - - map.insert("username".to_owned(), Value::String(user.name.clone())); - - if let Some(email) = user.email.as_ref() { - map.insert("email".to_owned(), Value::String(email.clone())); - } - }} + feature_cache! { + { + let cache = CACHE.read().unwrap(); + + map.insert("username".to_owned(), Value::String(cache.user.name.clone())); + + if let Some(email) = cache.user.email.as_ref() { + map.insert("email".to_owned(), Value::String(email.clone())); + } + } else { + let user = http::get_current_user()?; + + map.insert("username".to_owned(), Value::String(user.name.clone())); + + if let Some(email) = user.email.as_ref() { + map.insert("email".to_owned(), Value::String(email.clone())); + } + } + } let edited = f(EditProfile(map)).0; diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 461fe8c..68f31ef 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -386,26 +386,28 @@ fn handle_event<H: EventHandler + 'static>(event: Event, let context = context(conn, data); let h = event_handler.clone(); - feature_cache! {{ - // This is safe to unwrap, as the update would have created - // the member if it did not exist. So, there is be _no_ way - // that this could fail under any circumstance. - let after = CACHE.read() - .unwrap() - .member(event.guild_id, event.user.id) - .unwrap() - .clone(); - - tokio_handle.spawn_fn(move || { - h.on_guild_member_update(context, _before, after); - Ok(()) - }); - } else { - tokio_handle.spawn_fn(move || { - h.on_guild_member_update(context, event); - Ok(()) - }); - }} + feature_cache! { + { + // This is safe to unwrap, as the update would have created + // the member if it did not exist. So, there is be _no_ way + // that this could fail under any circumstance. + let after = CACHE.read() + .unwrap() + .member(event.guild_id, event.user.id) + .unwrap() + .clone(); + + tokio_handle.spawn_fn(move || { + h.on_guild_member_update(context, _before, after); + Ok(()) + }); + } else { + tokio_handle.spawn_fn(move || { + h.on_guild_member_update(context, event); + Ok(()) + }); + } + } }, Event::GuildMembersChunk(event) => { update!(update_with_guild_members_chunk, event); @@ -484,23 +486,25 @@ fn handle_event<H: EventHandler + 'static>(event: Event, let context = context(conn, data); let h = event_handler.clone(); - feature_cache! {{ - let before = CACHE.read() - .unwrap() - .guilds - .get(&event.guild.id) - .cloned(); - - tokio_handle.spawn_fn(move || { - h.on_guild_update(context, before, event.guild); - Ok(()) - }); - } else { - tokio_handle.spawn_fn(move || { - h.on_guild_update(context, event.guild); - Ok(()) - }); - }} + feature_cache! { + { + let before = CACHE.read() + .unwrap() + .guilds + .get(&event.guild.id) + .cloned(); + + tokio_handle.spawn_fn(move || { + h.on_guild_update(context, before, event.guild); + Ok(()) + }); + } else { + tokio_handle.spawn_fn(move || { + h.on_guild_update(context, event.guild); + Ok(()) + }); + } + } }, // Already handled by the framework check macro Event::MessageCreate(_) => {}, @@ -593,28 +597,30 @@ fn handle_event<H: EventHandler + 'static>(event: Event, Event::Ready(event) => { update!(update_with_ready, event); - feature_cache!{{ - last_guild_create_time = now!(); - - let _ = wait_for_guilds() - .map(|_| { - let context = context(conn, data); - - let h = event_handler.clone(); - tokio_handle.spawn_fn(move || { - h.on_ready(context, event.ready); - Ok(()) - }); - }); - } else { - let context = context(conn, data); - - let h = event_handler.clone(); - tokio_handle.spawn_fn(move || { - h.on_ready(context, event.ready); - Ok(()) - }); - }} + feature_cache!{ + { + last_guild_create_time = now!(); + + let _ = wait_for_guilds() + .map(|_| { + let context = context(conn, data); + + let h = event_handler.clone(); + tokio_handle.spawn_fn(move || { + h.on_ready(context, event.ready); + Ok(()) + }); + }); + } else { + let context = context(conn, data); + + let h = event_handler.clone(); + tokio_handle.spawn_fn(move || { + h.on_ready(context, event.ready); + Ok(()) + }); + } + } }, Event::Resumed(event) => { let context = context(conn, data); diff --git a/src/gateway/shard.rs b/src/gateway/shard.rs index 6f6a949..028efeb 100644 --- a/src/gateway/shard.rs +++ b/src/gateway/shard.rs @@ -138,41 +138,43 @@ impl Shard { let session_id = None; let mut shard = - feature_voice! {{ - let (tx, rx) = mpsc::channel(); - - let user = http::get_current_user()?; - - Shard { - client, - current_presence, - heartbeat_instants, - heartbeat_interval, - last_heartbeat_acknowledged, - seq, - stage, - token, - session_id, - shard_info, - ws_url, - manager: VoiceManager::new(tx, user.id), - manager_rx: rx, - } - } else { - Shard { - client, - current_presence, - heartbeat_instants, - heartbeat_interval, - last_heartbeat_acknowledged, - seq, - stage, - token, - session_id, - shard_info, - ws_url, - } - }}; + feature_voice! { + { + let (tx, rx) = mpsc::channel(); + + let user = http::get_current_user()?; + + Shard { + client, + current_presence, + heartbeat_instants, + heartbeat_interval, + last_heartbeat_acknowledged, + seq, + stage, + token, + session_id, + shard_info, + ws_url, + manager: VoiceManager::new(tx, user.id), + manager_rx: rx, + } + } else { + Shard { + client, + current_presence, + heartbeat_instants, + heartbeat_interval, + last_heartbeat_acknowledged, + seq, + stage, + token, + session_id, + shard_info, + ws_url, + } + } + }; shard.identify()?; diff --git a/src/model/channel/reaction.rs b/src/model/channel/reaction.rs index be5dfb8..121bf43 100644 --- a/src/model/channel/reaction.rs +++ b/src/model/channel/reaction.rs @@ -46,31 +46,34 @@ impl Reaction { /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html /// [permissions]: permissions pub fn delete(&self) -> Result<()> { - let user_id = feature_cache! {{ - let user = if self.user_id == CACHE.read().unwrap().user.id { - None - } else { - Some(self.user_id.0) - }; - - // If the reaction is one _not_ made by the current user, then ensure - // that the current user has permission* to delete the reaction. - // - // Normally, users can only delete their own reactions. - // - // * The `Manage Messages` permission. - if user.is_some() { - let req = permissions::MANAGE_MESSAGES; - - if !utils::user_has_perms(self.channel_id, req).unwrap_or(true) { - return Err(Error::Model(ModelError::InvalidPermissions(req))); - } - } - - user - } else { - Some(self.user_id.0) - }}; + let user_id = + feature_cache! { + { + let user = if self.user_id == CACHE.read().unwrap().user.id { + None + } else { + Some(self.user_id.0) + }; + + // If the reaction is one _not_ made by the current user, then ensure + // that the current user has permission* to delete the reaction. + // + // Normally, users can only delete their own reactions. + // + // * The `Manage Messages` permission. + if user.is_some() { + let req = permissions::MANAGE_MESSAGES; + + if !utils::user_has_perms(self.channel_id, req).unwrap_or(true) { + return Err(Error::Model(ModelError::InvalidPermissions(req))); + } + } + + user + } else { + Some(self.user_id.0) + } + }; http::delete_reaction(self.channel_id.0, self.message_id.0, user_id, &self.emoji) } diff --git a/src/model/user.rs b/src/model/user.rs index 66b7285..359d497 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -492,35 +492,38 @@ impl User { return Err(Error::Model(ModelError::MessagingBot)); } - let private_channel_id = feature_cache! {{ - let finding = { - let cache = CACHE.read().unwrap(); - - let finding = cache.private_channels - .values() - .map(|ch| ch.read().unwrap()) - .find(|ch| ch.recipient.read().unwrap().id == self.id) - .map(|ch| ch.id); - - finding - }; - - if let Some(finding) = finding { - finding - } else { - let map = json!({ - "recipient_id": self.id.0, - }); - - http::create_private_channel(&map)?.id - } - } else { - let map = json!({ - "recipient_id": self.id.0, - }); - - http::create_private_channel(&map)?.id - }}; + let private_channel_id = + feature_cache! { + { + let finding = { + let cache = CACHE.read().unwrap(); + + let finding = cache.private_channels + .values() + .map(|ch| ch.read().unwrap()) + .find(|ch| ch.recipient.read().unwrap().id == self.id) + .map(|ch| ch.id); + + finding + }; + + if let Some(finding) = finding { + finding + } else { + let map = json!({ + "recipient_id": self.id.0, + }); + + http::create_private_channel(&map)?.id + } + } else { + let map = json!({ + "recipient_id": self.id.0, + }); + + http::create_private_channel(&map)?.id + } + }; private_channel_id.send_message(f) } diff --git a/src/voice/streamer.rs b/src/voice/streamer.rs index 5f05879..cf62d27 100644 --- a/src/voice/streamer.rs +++ b/src/voice/streamer.rs @@ -48,6 +48,11 @@ impl<R: Read + Send> AudioSource for InputSource<R> { fn read_opus_frame(&mut self) -> Option<Vec<u8>> { match self.reader.read_i16::<LittleEndian>() { Ok(size) => { + if size <= 0 { + warn!("Invalid opus frame size: {}", size); + return None; + } + let mut frame = Vec::with_capacity(size as usize); { |