From 150e1884010fb592e4a72de2217fc827bb1c43bb Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Mon, 13 Oct 2025 09:31:40 +0200 Subject: pkg/email/lore: demand patches in patch series emails On LKML, users sometimes reply to a patch series while keeping the original title. At the same time, sometimes new series are sent as a reply to the previous versions. It all confuses the lore archive parsing logic. When reading the archive, remember if the patch were present. If not, mark the series as corrupted and thus prevent is appearance in syz-cluster. --- pkg/email/lore/parse.go | 5 +++++ pkg/email/lore/parse_test.go | 44 ++++++++++++++++++++++++++++++++++---------- pkg/email/lore/read.go | 2 +- 3 files changed, 40 insertions(+), 11 deletions(-) (limited to 'pkg') diff --git a/pkg/email/lore/parse.go b/pkg/email/lore/parse.go index d71e2a362..3b044bf21 100644 --- a/pkg/email/lore/parse.go +++ b/pkg/email/lore/parse.go @@ -93,6 +93,11 @@ func PatchSeries(emails []*Email) []*Series { // The cover email is not of interest. continue } + if !email.HasPatch { + // Sometimes users reply to the series keeping the original subject. + // Ignore such messages. + continue + } if hasSeq[seq] { // It's weird if that really happens, but let's skip for now. continue diff --git a/pkg/email/lore/parse_test.go b/pkg/email/lore/parse_test.go index 743ffc976..196f9c486 100644 --- a/pkg/email/lore/parse_test.go +++ b/pkg/email/lore/parse_test.go @@ -13,6 +13,7 @@ import ( "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/pkg/email" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestThreadsCollection(t *testing.T) { @@ -381,6 +382,17 @@ func TestDiscussionType(t *testing.T) { } } +const dummyPatch = `diff --git a/kernel/kcov.c b/kernel/kcov.c +index 85e5546cd791..949ea4574412 100644 +--- a/kernel/kcov.c ++++ b/kernel/kcov.c +@@ -127,7 +127,6 @@ void kcov_task_exit(struct task_struct *t) + if (kcov == NULL) + return; +- spin_lock(&kcov->lock); + if (WARN_ON(kcov->t != t)) { +` + func TestParseSeries(t *testing.T) { messages := []string{ // A simple patch series. @@ -390,8 +402,7 @@ Message-ID: From: UserA Content-Type: text/plain - -Some text`, +` + dummyPatch, // A series with a cover. `Date: Sun, 7 May 2017 19:55:00 -0700 Subject: [PATCH net v2 00/02] A longer series @@ -409,8 +420,7 @@ To: UserA , UserB Content-Type: text/plain In-Reply-To: - -Patch 1/2`, +` + dummyPatch, `Date: Sun, 7 May 2017 19:56:00 -0700 Subject: [PATCH net v2 02/02] Second patch Message-ID: @@ -419,16 +429,24 @@ To: UserA , UserB Content-Type: text/plain In-Reply-To: - -Patch 2/2`, - // Missing patches. +` + dummyPatch, + // Some missing patches. `Date: Sun, 7 May 2017 19:57:00 -0700 Subject: [PATCH 01/03] Series Message-ID: From: Someone Content-Type: text/plain -Bug report`, +` + dummyPatch, + // Reply with a patch subject. + `Date: Sun, 7 May 2017 19:57:00 -0700 +Subject: [PATCH] Series +Message-ID: +From: Someone +Content-Type: text/plain +In-Reply-To: + +No patch, just text`, } var emails []*Email @@ -441,7 +459,7 @@ Bug report`, } series := PatchSeries(emails) - assert.Len(t, series, 3) + assert.Len(t, series, 4) expectPerID := map[string]*Series{ "": { @@ -480,6 +498,12 @@ Bug report`, }, }, }, + "": { + Subject: "Series", + Version: 1, + Corrupted: "the subject mentions 1 patches, 0 are found", + Patches: nil, + }, } for _, s := range series { expect := expectPerID[s.MessageID] @@ -491,7 +515,7 @@ Bug report`, assert.Equal(t, expect.Corrupted, s.Corrupted, "corrupted differs") assert.Equal(t, expect.Subject, s.Subject, "subject differs") assert.Equal(t, expect.Version, s.Version, "version differs") - assert.Len(t, s.Patches, len(expect.Patches), "patch count differs") + require.Len(t, s.Patches, len(expect.Patches), "patch count differs") for i, expectPatch := range expect.Patches { got := s.Patches[i] assert.Equal(t, expectPatch.Seq, got.Seq, "seq differs") diff --git a/pkg/email/lore/read.go b/pkg/email/lore/read.go index 90a462d9a..133061a28 100644 --- a/pkg/email/lore/read.go +++ b/pkg/email/lore/read.go @@ -54,7 +54,7 @@ func emailFromRaw(body []byte, emails, domains []string) (*Email, error) { if err != nil { return nil, err } - ret := &Email{Email: msg} + ret := &Email{Email: msg, HasPatch: msg.Patch != ""} // Keep memory consumption low. ret.Body = "" ret.Patch = "" -- cgit mrf-deployment