From 3a45bed07499e8bf3c0717084722f5247b9b1cc2 Mon Sep 17 00:00:00 2001 From: Arpit Jain Date: Sun, 28 Jun 2026 12:30:28 +0900 Subject: [PATCH] fix(meta): RemoveFinalizer handles duplicate finalizers without panicking RemoveFinalizer mutated the finalizer slice in place while ranging over it by index. range evaluates len(f) once at loop start, but the append(f[:i], f[i+1:]...) call shrinks f in place, so after a removal the loop keeps walking original indices into the now-shorter backing array. When the target finalizer appears more than once this either panics with slice bounds out of range or silently leaves one occurrence behind. Replace the index-mutating loop with slices.DeleteFunc, which removes all matching elements correctly in a single pass. The slices package is already imported and used by the sibling AddFinalizer/FinalizerExists. Add regression cases for duplicate finalizers to TestRemoveFinalizer. Signed-off-by: Arpit Jain --- pkg/meta/meta.go | 8 +++----- pkg/meta/meta_test.go | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/pkg/meta/meta.go b/pkg/meta/meta.go index ac729b7f2..1e14c4176 100644 --- a/pkg/meta/meta.go +++ b/pkg/meta/meta.go @@ -190,11 +190,9 @@ func AddFinalizer(o metav1.Object, finalizer string) { // RemoveFinalizer from the supplied Kubernetes object's metadata. func RemoveFinalizer(o metav1.Object, finalizer string) { f := o.GetFinalizers() - for i, e := range f { - if e == finalizer { - f = append(f[:i], f[i+1:]...) - } - } + f = slices.DeleteFunc(f, func(e string) bool { + return e == finalizer + }) o.SetFinalizers(f) } diff --git a/pkg/meta/meta_test.go b/pkg/meta/meta_test.go index e68034421..7bc249011 100644 --- a/pkg/meta/meta_test.go +++ b/pkg/meta/meta_test.go @@ -538,6 +538,28 @@ func TestRemoveFinalizer(t *testing.T) { }, want: []string{funalizer}, }, + "DuplicateFinalizersExist": { + args: args{ + o: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Finalizers: []string{finalizer, finalizer}, + }, + }, + finalizer: finalizer, + }, + want: []string{}, + }, + "DuplicateFinalizersWithOther": { + args: args{ + o: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Finalizers: []string{finalizer, funalizer, finalizer}, + }, + }, + finalizer: finalizer, + }, + want: []string{funalizer}, + }, } for name, tc := range cases {