3
0
mirror of https://github.com/ergochat/ergo.git synced 2025-02-16 21:50:39 +01:00
In #2058 we introduced two bugs:

* A nil dereference when an outside user attempts to speak
* Ordinary copy of a modes.ModeSet (which should only be accessed via atomics)

This fixes both issues.
This commit is contained in:
Shivaram Lingamneni 2023-05-22 12:29:55 -04:00
parent 2c0928f94d
commit e84793d7ee

View File

@ -1228,20 +1228,26 @@ func (channel *Channel) CanSpeak(client *Client) (bool, modes.Mode) {
channel.stateMutex.RLock() channel.stateMutex.RLock()
memberData, hasClient := channel.members[client] memberData, hasClient := channel.members[client]
channel.stateMutex.RUnlock() channel.stateMutex.RUnlock()
clientModes := memberData.modes
highestMode := func() modes.Mode {
if !hasClient {
return modes.Mode(0)
}
return memberData.modes.HighestChannelUserMode()
}
if !hasClient && channel.flags.HasMode(modes.NoOutside) { if !hasClient && channel.flags.HasMode(modes.NoOutside) {
// TODO: enforce regular +b bans on -n channels? // TODO: enforce regular +b bans on -n channels?
return false, modes.NoOutside return false, modes.NoOutside
} }
if channel.isMuted(client) && clientModes.HighestChannelUserMode() == modes.Mode(0) { if channel.isMuted(client) && highestMode() == modes.Mode(0) {
return false, modes.BanMask return false, modes.BanMask
} }
if channel.flags.HasMode(modes.Moderated) && clientModes.HighestChannelUserMode() == modes.Mode(0) { if channel.flags.HasMode(modes.Moderated) && highestMode() == modes.Mode(0) {
return false, modes.Moderated return false, modes.Moderated
} }
if channel.flags.HasMode(modes.RegisteredOnlySpeak) && client.Account() == "" && if channel.flags.HasMode(modes.RegisteredOnlySpeak) && client.Account() == "" &&
clientModes.HighestChannelUserMode() == modes.Mode(0) { highestMode() == modes.Mode(0) {
return false, modes.RegisteredOnlySpeak return false, modes.RegisteredOnlySpeak
} }
return true, modes.Mode('?') return true, modes.Mode('?')