diff --git a/.changeset/metrics-batch-str-data-index.md b/.changeset/metrics-batch-str-data-index.md new file mode 100644 index 000000000..e0cc37e8a --- /dev/null +++ b/.changeset/metrics-batch-str-data-index.md @@ -0,0 +1,5 @@ +--- +"github.com/livekit/protocol": patch +--- + +`utils.MetricsBatchBuilder.Merge` rejects out-of-range `str_data` indexes on 32-bit builds. diff --git a/utils/metrics_batch_builder.go b/utils/metrics_batch_builder.go index d6fc54e21..1a12ae6f3 100644 --- a/utils/metrics_batch_builder.go +++ b/utils/metrics_batch_builder.go @@ -309,7 +309,7 @@ func (m *MetricsBatchBuilder) translateStrDataIndex(strData []string, index uint } baseIdx := index - uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) - if len(strData) <= int(baseIdx) { + if uint64(len(strData)) <= uint64(baseIdx) { return 0, false } @@ -325,7 +325,7 @@ func getStrDataForIndex(mb *livekit.MetricsBatch, index uint32) (string, bool) { } baseIdx := index - uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) - if len(mb.StrData) <= int(baseIdx) { + if uint64(len(mb.StrData)) <= uint64(baseIdx) { return "", false } diff --git a/utils/metrics_batch_builder_test.go b/utils/metrics_batch_builder_test.go index a5774be93..fbc9d93df 100644 --- a/utils/metrics_batch_builder_test.go +++ b/utils/metrics_batch_builder_test.go @@ -596,4 +596,31 @@ func TestMetricsBatchBuilder(t *testing.T) { mb := mbb.ToProto() require.True(t, proto.Equal(expected, mb)) }) + + t.Run("merge str data index beyond int32", func(t *testing.T) { + // index past the end must be rejected even where int is 32 bits + const huge = ^uint32(0) + mbb := NewMetricsBatchBuilder() + require.NotPanics(t, func() { + mbb.Merge(&livekit.MetricsBatch{ + StrData: []string{"PA"}, + TimeSeries: []*livekit.TimeSeriesMetric{ + {Label: huge, ParticipantIdentity: huge, TrackSid: huge, Rid: huge}, + {Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), ParticipantIdentity: huge}, + }, + Events: []*livekit.EventMetric{ + {Label: huge, ParticipantIdentity: huge, TrackSid: huge, Rid: huge}, + {Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), ParticipantIdentity: huge}, + }, + }) + }) + mb := mbb.ToProto() + require.Len(t, mb.TimeSeries, 2) + require.Len(t, mb.Events, 2) + require.Empty(t, mb.StrData) + for _, ts := range mb.TimeSeries { + require.Zero(t, ts.ParticipantIdentity) + require.Zero(t, ts.TrackSid) + } + }) }