From 35c0a1463d60a5371429908ccf8066a40d80638c Mon Sep 17 00:00:00 2001 From: Tamim Bin Hakim Date: Sat, 6 Jun 2026 16:36:31 +0600 Subject: [PATCH] fix: trim whitespace in relay --ports list `croc relay --ports "9009, 9010, 9011"` split the value on "," without trimming, producing invalid port strings like " 9010" that fail to bind and then get advertised to clients in the relay banner. Trim each entry and drop empties so spaced or trailing-comma lists behave the same as "9009,9010", matching how the comma-separated --exclude flag is already handled. --- src/cli/cli.go | 15 +++++++++++++- src/cli/cli_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/cli/cli.go b/src/cli/cli.go index 303b20416..e7b77f5b8 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -293,6 +293,19 @@ func shouldExitForUnixSendCode(goos string, codeFlagSet, classicInsecureMode boo return goos != "windows" && codeFlagSet && !classicInsecureMode && envSecret == "" } +// parseRelayPorts splits a comma-separated --ports value, trimming whitespace +// around each entry and dropping empties. This keeps "9009, 9010," working the +// same as "9009,9010" instead of producing invalid port strings like " 9010". +func parseRelayPorts(portsFlag string) []string { + var ports []string + for _, p := range strings.Split(portsFlag, ",") { + if p = strings.TrimSpace(p); p != "" { + ports = append(ports, p) + } + } + return ports +} + func send(c *cli.Context) (err error) { setDebugLevel(c) comm.Socks5Proxy = c.String("socks5") @@ -793,7 +806,7 @@ func relay(c *cli.Context) (err error) { var ports []string if c.IsSet("ports") { - ports = strings.Split(c.String("ports"), ",") + ports = parseRelayPorts(c.String("ports")) } else { portString := c.Int("port") if portString == 0 { diff --git a/src/cli/cli_test.go b/src/cli/cli_test.go index 6cdc6992e..a5b97b58f 100644 --- a/src/cli/cli_test.go +++ b/src/cli/cli_test.go @@ -1,6 +1,52 @@ package cli -import "testing" +import ( + "reflect" + "testing" +) + +func TestParseRelayPorts(t *testing.T) { + tests := []struct { + name string + in string + want []string + }{ + { + name: "plain comma separated", + in: "9009,9010,9011", + want: []string{"9009", "9010", "9011"}, + }, + { + name: "spaces after commas are trimmed", + in: "9009, 9010, 9011", + want: []string{"9009", "9010", "9011"}, + }, + { + name: "surrounding and trailing empties are dropped", + in: " 9009 ,, 9010 ,", + want: []string{"9009", "9010"}, + }, + { + name: "single port", + in: "9009", + want: []string{"9009"}, + }, + { + name: "empty string yields no ports", + in: "", + want: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := parseRelayPorts(tt.in) + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("parseRelayPorts(%q) = %#v, want %#v", tt.in, got, tt.want) + } + }) + } +} func TestResolveSendSharedSecret(t *testing.T) { t.Run("uses env secret", func(t *testing.T) {