Initialize context actions with their client

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 14:22:46 -04:00
committed by Brandon McGinty
parent 12dfa562d2
commit f67cc657eb
5 changed files with 62 additions and 8 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ Priority 0: security and crashers
ensure channel close/send are serialized. Do not rely on the TCP read
routine being serialized with UDP.
3. Context actions panic on receipt and on trigger
[x] 3. Context actions panic on receipt and on trigger
Files: gumble/gumble/client.go, gumble/gumble/handlers.go,
gumble/gumble/contextaction.go
Client.ContextActions is never initialized, so the first
+5 -4
View File
@@ -118,10 +118,11 @@ func DialWithDialer(dialer *net.Dialer, config *Config, tlsConfig *tls.Config) (
}
client := &Client{
Conn: NewConn(conn),
Config: config,
Users: make(Users),
Channels: make(Channels),
Conn: NewConn(conn),
Config: config,
Users: make(Users),
Channels: make(Channels),
ContextActions: make(ContextActions),
permissions: make(map[uint32]*Permission),
@@ -0,0 +1,52 @@
package gumble
import (
"net"
"testing"
"git.stormux.org/storm/barnard/gumble/gumble/MumbleProto"
"google.golang.org/protobuf/proto"
)
// Regression: server context-action adds wrote to a nil map and the resulting
// action had no owning client, so Trigger panicked.
func TestContextActionAddAndTrigger(t *testing.T) {
clientConn, serverConn := net.Pipe()
defer serverConn.Close()
c := &Client{Config: NewConfig(), Users: make(Users), Channels: make(Channels), ContextActions: make(ContextActions)}
c.Conn = NewConn(clientConn)
action, operation := "test", MumbleProto.ContextActionModify_Add
data, err := proto.Marshal(&MumbleProto.ContextActionModify{Action: &action, Operation: &operation})
if err != nil {
t.Fatal(err)
}
if err := c.handleContextActionModify(data); err != nil {
t.Fatal(err)
}
added := c.ContextActions[action]
if added == nil || added.client != c {
t.Fatal("action was not initialized with its client")
}
written := make(chan error, 1)
go func() { _, _, err := NewConn(serverConn).ReadPacket(); written <- err }()
added.Trigger()
if err := <-written; err != nil {
t.Fatalf("trigger did not write: %v", err)
}
remove := MumbleProto.ContextActionModify_Remove
data, _ = proto.Marshal(&MumbleProto.ContextActionModify{Action: &action, Operation: &remove})
if err := c.handleContextActionModify(data); err != nil {
t.Fatal(err)
}
if c.ContextActions[action] != nil {
t.Fatal("action was not removed")
}
}
// Regression: the documented bit layout disagreed with SemanticVersion.
func TestSemanticVersionKnownLayout(t *testing.T) {
major, minor, patch := (&Version{Version: 1<<16 | 5<<8 | 2}).SemanticVersion()
if major != 1 || minor != 5 || patch != 2 {
t.Fatalf("got %d.%d.%d", major, minor, patch)
}
}
+3 -2
View File
@@ -3,9 +3,10 @@ package gumble
// ContextActions is a map of ContextActions.
type ContextActions map[string]*ContextAction
func (c ContextActions) create(action string) *ContextAction {
func (c ContextActions) create(client *Client, action string) *ContextAction {
contextAction := &ContextAction{
Name: action,
Name: action,
client: client,
}
c[action] = contextAction
return contextAction
+1 -1
View File
@@ -1029,7 +1029,7 @@ func (c *Client) handleContextActionModify(buffer []byte) error {
return nil
}
event.Type = ContextActionAdd
contextAction := c.ContextActions.create(*packet.Action)
contextAction := c.ContextActions.create(c, *packet.Action)
if packet.Text != nil {
contextAction.Label = *packet.Text
}