From bf2613fa64fbbe447f1eec26aac5195d5cd02f15 Mon Sep 17 00:00:00 2001 From: Josh Knight Date: Sat, 1 Jun 2024 11:41:20 -0400 Subject: [PATCH] Fix crash when warning offline user When a warned screenname is offline ras would attempt to send an empty SNAC, which caused a crash when marshalling the nil value. Fix by sending a proper error message, and also detect the nil value when marshalling so we don't crash on future empty snacs. Closes #38 --- foodgroup/icbm.go | 11 ++++++++++- wire/encode.go | 4 ++++ wire/encode_test.go | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/foodgroup/icbm.go b/foodgroup/icbm.go index 56becf68..a81efea1 100644 --- a/foodgroup/icbm.go +++ b/foodgroup/icbm.go @@ -213,7 +213,16 @@ func (s ICBMService) EvilRequest(ctx context.Context, sess *state.Session, inFra recipSess := s.messageRelayer.RetrieveByScreenName(inBody.ScreenName) if recipSess == nil { - return wire.SNACMessage{}, nil + return wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICBM, + SubGroup: wire.ICBMErr, + RequestID: inFrame.RequestID, + }, + Body: wire.SNACError{ + Code: wire.ErrorCodeNotLoggedOn, + }, + }, nil } increase := evilDelta diff --git a/wire/encode.go b/wire/encode.go index 8f4bfd06..4b7e1010 100644 --- a/wire/encode.go +++ b/wire/encode.go @@ -10,12 +10,16 @@ import ( ) var ErrMarshalFailure = errors.New("failed to marshal") +var ErrMarshalFailureNilSNAC = errors.New("attempting to marshal a nil SNAC") func Marshal(v any, w io.Writer) error { return marshal(reflect.TypeOf(v), reflect.ValueOf(v), "", w) } func marshal(t reflect.Type, v reflect.Value, tag reflect.StructTag, w io.Writer) error { + if t == nil { + return ErrMarshalFailureNilSNAC + } switch t.Kind() { case reflect.Struct: for i := 0; i < t.NumField(); i++ { diff --git a/wire/encode_test.go b/wire/encode_test.go index 8cffce87..e34bfcc2 100644 --- a/wire/encode_test.go +++ b/wire/encode_test.go @@ -323,6 +323,12 @@ func TestMarshal(t *testing.T) { }, wantErr: ErrMarshalFailure, }, + { + name: "empty snac", + w: &bytes.Buffer{}, + given: nil, + wantErr: ErrMarshalFailureNilSNAC, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {