From 6b96837eb981763a95aa6e41bd7a2deec8cfe2ee Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Sun, 30 Aug 2026 18:42:03 +0300 Subject: [PATCH] internal: fix MaxSizeSubjectsListForLog off-by-one when maxToDisplay is 0 The loop appended before checking the length, so with maxToDisplay=0 one domain leaked into the output before the break check. Reorder so the length check comes first. Signed-off-by: Mohammed Al Sahaf --- internal/logs.go | 2 +- internal/logs_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 internal/logs_test.go diff --git a/internal/logs.go b/internal/logs.go index 4ed4a572e..9f8af0553 100644 --- a/internal/logs.go +++ b/internal/logs.go @@ -10,10 +10,10 @@ func MaxSizeSubjectsListForLog(subjects map[string]struct{}, maxToDisplay int) [ numberOfNamesToDisplay := min(len(subjects), maxToDisplay) domainsToDisplay := make([]string, 0, numberOfNamesToDisplay) for domain := range subjects { - domainsToDisplay = append(domainsToDisplay, domain) if len(domainsToDisplay) >= numberOfNamesToDisplay { break } + domainsToDisplay = append(domainsToDisplay, domain) } if len(subjects) > maxToDisplay { domainsToDisplay = append(domainsToDisplay, fmt.Sprintf("(and %d more...)", len(subjects)-maxToDisplay)) diff --git a/internal/logs_test.go b/internal/logs_test.go new file mode 100644 index 000000000..afbd5a462 --- /dev/null +++ b/internal/logs_test.go @@ -0,0 +1,34 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import "testing" + +// TestMaxSizeSubjectsListForLog_MaxIsZero is the regression test for +// the off-by-one where a domain leaked into the output when maxToDisplay +// was 0. +func TestMaxSizeSubjectsListForLog_MaxIsZero(t *testing.T) { + subjects := map[string]struct{}{ + "a.com": {}, + "b.com": {}, + } + got := MaxSizeSubjectsListForLog(subjects, 0) + if len(got) != 1 { + t.Fatalf("expected only the suffix entry, got %d items: %v", len(got), got) + } + if len(got[0]) < 4 || got[0][:4] != "(and" { + t.Errorf("expected the only entry to be the '(and N more...)' suffix, got %q", got[0]) + } +}