From 3d1b4d33ae85d5e4f6821b69f9cd26e39145d0c6 Mon Sep 17 00:00:00 2001 From: Tian Pan Date: Thu, 29 Oct 2026 17:46:08 -0700 Subject: [PATCH] fix: count IP allowlist descriptions in Unicode characters --- pkg/types/ipallowlist.go | 3 ++- pkg/types/ipallowlist_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/types/ipallowlist.go b/pkg/types/ipallowlist.go index d2346e92..5ec1d17f 100644 --- a/pkg/types/ipallowlist.go +++ b/pkg/types/ipallowlist.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "strings" + "unicode/utf8" "github.com/render-oss/cli/pkg/client" ) @@ -38,7 +39,7 @@ func ParseIPAllowListEntry(raw string) (cidrBlock string, description string, er cidrBlock = ipNet.String() const maxDescriptionLength = 255 - if len(description) > maxDescriptionLength { + if utf8.RuneCountInString(description) > maxDescriptionLength { return "", "", fmt.Errorf("invalid --ip-allow-list %q: description exceeds %d characters", raw, maxDescriptionLength) } diff --git a/pkg/types/ipallowlist_test.go b/pkg/types/ipallowlist_test.go index 2bfd6fa6..29ce9302 100644 --- a/pkg/types/ipallowlist_test.go +++ b/pkg/types/ipallowlist_test.go @@ -1,6 +1,7 @@ package types_test import ( + "strings" "testing" "github.com/render-oss/cli/pkg/types" @@ -61,6 +62,32 @@ func TestParseIPAllowListEntry(t *testing.T) { }) } +func TestParseIPAllowListEntryDescriptionLength(t *testing.T) { + for _, tc := range []struct { + name string + description string + ok bool + }{ + {"255 ASCII characters", strings.Repeat("x", 255), true}, + {"256 ASCII characters", strings.Repeat("x", 256), false}, + {"255 multi-byte characters", strings.Repeat("雪", 255), true}, + {"256 multi-byte characters", strings.Repeat("雪", 256), false}, + {"64 emoji", strings.Repeat("😀", 64), true}, + {"punctuation and Unicode", "QA,office=入口,description=kept", true}, + } { + t.Run(tc.name, func(t *testing.T) { + cidr, desc, err := types.ParseIPAllowListEntry("cidr=10.0.0.0/8,description=" + tc.description) + if !tc.ok { + require.ErrorContains(t, err, "description exceeds 255 characters") + return + } + require.NoError(t, err) + assert.Equal(t, "10.0.0.0/8", cidr) + assert.Equal(t, tc.description, desc) + }) + } +} + func TestParseIPAllowList(t *testing.T) { t.Run("parses each entry into a CidrBlockAndDescription", func(t *testing.T) { out, err := types.ParseIPAllowList([]string{