From 1c4a7e8556f019324653c52580c072bff53b74f1 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 21 Jan 2026 13:44:14 -0500 Subject: [PATCH] fix(scanner): prevent infinite recursion in pid configuration closes #4920 Signed-off-by: Deluan --- model/metadata/persistent_ids.go | 9 +++++++-- model/metadata/persistent_ids_test.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/model/metadata/persistent_ids.go b/model/metadata/persistent_ids.go index b4588294..d4222441 100644 --- a/model/metadata/persistent_ids.go +++ b/model/metadata/persistent_ids.go @@ -8,6 +8,7 @@ import ( "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/consts" + "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model/id" "github.com/navidrome/navidrome/utils" @@ -26,10 +27,14 @@ type getPIDFunc = func(mf model.MediaFile, md Metadata, spec string, prependLibI func createGetPID(hash hashFunc) getPIDFunc { var getPID getPIDFunc - getAttr := func(mf model.MediaFile, md Metadata, attr string, prependLibId bool) string { + getAttr := func(mf model.MediaFile, md Metadata, attr string, prependLibId bool, spec string) string { attr = strings.TrimSpace(strings.ToLower(attr)) switch attr { case "albumid": + if spec == conf.Server.PID.Album { + log.Error("Recursive PID definition detected, ignoring `albumid`", "spec", spec) + return "" + } return getPID(mf, md, conf.Server.PID.Album, prependLibId) case "folder": return filepath.Dir(mf.Path) @@ -49,7 +54,7 @@ func createGetPID(hash hashFunc) getPIDFunc { attributes := strings.Split(field, ",") hasValue := false values := slice.Map(attributes, func(attr string) string { - v := getAttr(mf, md, attr, prependLibId) + v := getAttr(mf, md, attr, prependLibId, spec) if v != "" { hasValue = true } diff --git a/model/metadata/persistent_ids_test.go b/model/metadata/persistent_ids_test.go index 7ae0c91f..ad81eaa5 100644 --- a/model/metadata/persistent_ids_test.go +++ b/model/metadata/persistent_ids_test.go @@ -114,6 +114,24 @@ var _ = Describe("getPID", func() { Expect(getPID(mf, md, spec, false)).To(Equal("(album name)")) }) }) + + When("albumid configuration refers to albumid recursively", func() { + It("should avoid infinite recursion", func() { + // Reproduce the issue from #4920 + conf.Server.PID.Album = "albumid,album,albumversion,releasedate" + spec := conf.Server.PID.Album + md.tags = map[model.TagName][]string{ + "album": {"Album Name"}, + "albumversion": {"Version"}, + "releasedate": {"2022"}, + } + // Should not panic and return a valid PID ignoring the recursive "albumid" + Expect(func() { + pid := getPID(mf, md, spec, false) + Expect(pid).To(Equal("(\\album name\\Version\\2022)")) + }).To(Not(Panic())) + }) + }) }) Context("edge cases", func() {