4
0
Эх сурвалжийг харах

override for QIP 2005 TLV len bug

Mike 1 жил өмнө
parent
commit
a7596ee773

+ 7 - 1
server/oscar/handler/icq.go

@@ -130,8 +130,14 @@ func (rt ICQHandler) DBQuery(ctx context.Context, sess *state.Session, inFrame w
 				return err
 			}
 		case wire.ICQDBQueryMetaReqSearchByUIN2:
+			rest := buf.Bytes()
+			if bytes.HasPrefix(rest, []byte{0x36, 0x01, 0x06, 0x00}) && len(rest) == 8 {
+				// fix incorrect TLV len set by QIP 2005. it specifies len=6
+				// for a 4-byte value, causing the unmarshaler to return EOF.
+				rest[2] = 4
+			}
 			req := wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{}
-			if err := wire.UnmarshalLE(&req, buf); err != nil {
+			if err := wire.UnmarshalLE(&req, bytes.NewReader(rest)); err != nil {
 				return err
 			}
 			if err := rt.ICQService.FindByUIN2(ctx, sess, req, icqMD.Seq); err != nil {

+ 57 - 0
server/oscar/handler/icq_test.go

@@ -967,3 +967,60 @@ func TestICQHandler_DBQuery(t *testing.T) {
 		})
 	}
 }
+
+// Test workaround for QIP 2005 bug where TLV length is incorrect.
+func TestICQHandler_DBQuery_QIP2005UINSearchBug(t *testing.T) {
+	icqService := newMockICQService(t)
+
+	type ICQMetaRequest struct {
+		wire.ICQMetadata
+		ReqSubType  uint16
+		MetaRequest any
+	}
+
+	expect := wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{
+		TLVRestBlock: wire.TLVRestBlock{
+			TLVList: wire.TLVList{
+				wire.NewTLVBE(wire.ICQTLVTagsUIN, uint32(100009)),
+			},
+		},
+	}
+
+	icqService.EXPECT().
+		FindByUIN2(mock.Anything, &state.Session{}, expect, uint16(1)).
+		Return(nil)
+
+	rt := NewICQHandler(slog.Default(), icqService)
+
+	inBody := wire.SNAC_0x15_0x02_BQuery{
+		TLVRestBlock: wire.TLVRestBlock{
+			TLVList: wire.TLVList{
+				wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{
+					Message: ICQMetaRequest{
+						ICQMetadata: wire.ICQMetadata{
+							ReqType: wire.ICQDBQueryMetaReq,
+							Seq:     1,
+						},
+						ReqSubType: wire.ICQDBQueryMetaReqSearchByUIN2,
+						MetaRequest: wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{
+							TLVRestBlock: wire.TLVRestBlock{
+								TLVList: wire.TLVList{
+									wire.NewTLVBE(wire.ICQTLVTagsUIN, uint32(100009)),
+								},
+							},
+						},
+					},
+				}),
+			},
+		},
+	}
+
+	buf := &bytes.Buffer{}
+	assert.NoError(t, wire.MarshalBE(inBody, buf))
+
+	b := buf.Bytes()
+	b[18] = 6 // incorrectly set TLV length to 6 (should be 4)
+
+	err := rt.DBQuery(nil, &state.Session{}, wire.SNACFrame{}, buf, nil)
+	assert.NoError(t, err)
+}