Skip to content

Commit 06da1f0

Browse files
S7evinKclokepkegsay
authored
Add test for state_key size (#642)
* Add test for state_key event size * Update to latest complement/gmsl APIs --------- Co-authored-by: Patrick Cloke <[email protected]> Co-authored-by: kegsay <[email protected]> Co-authored-by: Kegan Dougal <[email protected]>
1 parent 8cb8581 commit 06da1f0

File tree

1 file changed

+133
-1
lines changed

1 file changed

+133
-1
lines changed

tests/federation_room_get_missing_events_test.go

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"net/http"
8+
"strings"
89
"testing"
910
"time"
1011

@@ -17,8 +18,8 @@ import (
1718

1819
"github.com/matrix-org/complement/b"
1920
"github.com/matrix-org/complement/client"
20-
"github.com/matrix-org/complement/helpers"
2121
"github.com/matrix-org/complement/federation"
22+
"github.com/matrix-org/complement/helpers"
2223
"github.com/matrix-org/complement/match"
2324
"github.com/matrix-org/complement/must"
2425
)
@@ -466,3 +467,134 @@ func TestInboundCanReturnMissingEvents(t *testing.T) {
466467
})
467468
}
468469
}
470+
471+
// This test verifies that an event with a too large state_key can be used as a prev_event
472+
// it is returned by a call to /get_missing_events and should pass event size checks.
473+
// TODO: Do the same checks for type, user_id and sender
474+
func TestOutboundFederationEventSizeGetMissingEvents(t *testing.T) {
475+
deployment := complement.Deploy(t, 1)
476+
defer deployment.Destroy(t)
477+
478+
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
479+
480+
srv := federation.NewServer(t, deployment,
481+
federation.HandleKeyRequests(),
482+
federation.HandleMakeSendJoinRequests(),
483+
// Handle any transactions that the homeserver may send when connecting to another homeserver (such as presence)
484+
federation.HandleTransactionRequests(nil, nil),
485+
)
486+
cancel := srv.Listen()
487+
defer cancel()
488+
489+
// register a handler for /get_missing_events, via a shim so that we can
490+
// behave differently as the test progresses.
491+
var onGetMissingEvents func(w http.ResponseWriter, req *http.Request)
492+
srv.Mux().HandleFunc("/_matrix/federation/v1/get_missing_events/{roomID}", func(w http.ResponseWriter, req *http.Request) {
493+
onGetMissingEvents(w, req)
494+
}).Methods("POST")
495+
496+
ver := alice.GetDefaultRoomVersion(t)
497+
charlie := srv.UserID("charlie")
498+
room := srv.MustMakeRoom(t, ver, federation.InitialRoomEvents(ver, charlie))
499+
roomAlias := srv.MakeAliasMapping("flibble", room.RoomID)
500+
// join the room
501+
alice.JoinRoom(t, roomAlias, nil)
502+
503+
latestEvent := room.Timeline[len(room.Timeline)-1]
504+
505+
// Sign this bad event which has a too large stateKey
506+
// Synapse always enforced 255 codepoints, but accepts events > 255 bytes.
507+
// Dendrite would fail to parse this event because it enforced 255 bytes, breaking older rooms.
508+
stateKey := strings.Repeat("💥", 70) // 280 bytes, 70 codepoints
509+
badEvent := b.Event{
510+
Type: "my.room.breaker",
511+
StateKey: &stateKey,
512+
Sender: charlie,
513+
Content: map[string]interface{}{},
514+
}
515+
content, err := json.Marshal(badEvent.Content)
516+
if err != nil {
517+
t.Fatalf("failed to marshal badEvent content %+v", badEvent.Content)
518+
}
519+
roomVersion := gomatrixserverlib.MustGetRoomVersion(ver)
520+
pe := &gomatrixserverlib.ProtoEvent{
521+
SenderID: badEvent.Sender,
522+
Depth: int64(room.Depth + 1), // depth starts at 1
523+
Type: badEvent.Type,
524+
StateKey: badEvent.StateKey,
525+
Content: content,
526+
RoomID: room.RoomID,
527+
PrevEvents: room.ForwardExtremities,
528+
}
529+
eb := roomVersion.NewEventBuilderFromProtoEvent(pe)
530+
stateNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(pe)
531+
if err != nil {
532+
t.Fatalf("failed to work out auth_events : %s", err)
533+
}
534+
eb.AuthEvents = room.AuthEvents(stateNeeded)
535+
536+
signedBadEvent, err := eb.Build(time.Now(), spec.ServerName(srv.ServerName()), srv.KeyID, srv.Priv)
537+
switch e := err.(type) {
538+
case nil:
539+
case gomatrixserverlib.EventValidationError:
540+
// ignore for now
541+
t.Logf("EventValidationError: %v", e)
542+
default:
543+
t.Fatalf("failed to sign event: %s: %s", err, signedBadEvent.JSON())
544+
}
545+
room.AddEvent(signedBadEvent)
546+
547+
// send the first "good" event, referencing the broken event as a prev_event
548+
sentEvent := srv.MustCreateEvent(t, room, federation.Event{
549+
Type: "m.room.message",
550+
Sender: charlie,
551+
Content: map[string]interface{}{
552+
"body": "Message 2",
553+
},
554+
})
555+
room.AddEvent(sentEvent)
556+
557+
waiter := helpers.NewWaiter()
558+
onGetMissingEvents = func(w http.ResponseWriter, req *http.Request) {
559+
defer waiter.Finish()
560+
must.MatchRequest(t, req, match.HTTPRequest{
561+
JSON: []match.JSON{
562+
match.JSONKeyEqual("earliest_events", []interface{}{latestEvent.EventID()}),
563+
match.JSONKeyEqual("latest_events", []interface{}{sentEvent.EventID()}),
564+
},
565+
})
566+
// return the bad event, which should result in the transaction failing.
567+
w.WriteHeader(200)
568+
res := struct {
569+
Events []json.RawMessage `json:"events"`
570+
}{
571+
Events: []json.RawMessage{signedBadEvent.JSON()},
572+
}
573+
var responseBytes []byte
574+
responseBytes, err = json.Marshal(&res)
575+
must.NotError(t, "failed to marshal response", err)
576+
w.Write(responseBytes)
577+
}
578+
579+
fedClient := srv.FederationClient(deployment)
580+
resp, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{
581+
TransactionID: "wut",
582+
Origin: spec.ServerName(srv.ServerName()),
583+
Destination: spec.ServerName("hs1"),
584+
PDUs: []json.RawMessage{
585+
sentEvent.JSON(),
586+
},
587+
})
588+
waiter.Wait(t, 5*time.Second)
589+
must.NotError(t, "SendTransaction errored", err)
590+
if len(resp.PDUs) != 1 {
591+
t.Fatalf("got %d errors, want 1", len(resp.PDUs))
592+
}
593+
_, ok := resp.PDUs[sentEvent.EventID()]
594+
if !ok {
595+
t.Fatalf("wrong PDU returned from send transaction, got %v want %s", resp.PDUs, sentEvent.EventID())
596+
}
597+
598+
// Alice should receive the sent event, even though the "bad" event has a too large state key
599+
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncTimelineHasEventID(room.RoomID, sentEvent.EventID()))
600+
}

0 commit comments

Comments
 (0)