Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions internal/util/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ func NormaliseBaseURL(baseURL string) string {
return baseURL
}

// IsPortAvailable checks if a port is available by attempting to bind to it
// IsPortAvailable checks if a port is available by attempting to bind to it.
// Strips brackets from IPv6 addresses since net.JoinHostPort adds them.
func IsPortAvailable(host string, port int) bool {
listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
ipStr := strings.Trim(host, "[]")
listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", net.JoinHostPort(ipStr, strconv.Itoa(port)))
Comment on lines +56 to +57
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Go strings.Trim cutset semantics vs TrimPrefix/TrimSuffix for bracket handling in host parsing

💡 Result:

In Go, strings.Trim(s, cutset) removes all leading and trailing Unicode code points present in the cutset from s. For bracket handling in host parsing (e.g., extracting bare hostname from "[::1]" or "[fe80::1]"), using Trim(s, "[]") correctly removes the leading '[' and trailing ']' because they are at the ends and match the cutset [1][2]. This works since Trim repeatedly removes any characters from the cutset from both ends until none remain [1]. For example, strings.Trim("[::1]", "[]") yields "::1" [2 shows semantics; applies here].

Citations:


🏁 Script executed:

sed -n '50,60p' internal/util/network.go

Repository: thushan/olla

Length of output: 468


🏁 Script executed:

python3 << 'EOF'
# Test strings.Trim behaviour with edge cases
test_cases = [
    ("[::1]", "correct IPv6 with brackets"),
    ("[::]", "IPv6 all zeros with brackets"),
    ("[::", "malformed: missing closing bracket"),
    ("::] ", "malformed: missing opening bracket"),
    ("]]::[[", "malformed: extra brackets"),
]

print("Simulating strings.Trim(host, '[]') behaviour:")
print("-" * 60)

for test_input, description in test_cases:
    # strings.Trim removes all leading/trailing chars from cutset
    result = test_input.strip("[]")
    print(f"Input: {test_input!r:15} ({description})")
    print(f"After Trim: {result!r}")
    print()
EOF

Repository: thushan/olla

Length of output: 534


Strip IPv6 brackets only when they form a matched pair

On line 56, strings.Trim(host, "[]") silently normalises malformed input. For example, [:: becomes :: instead of failing, which masks configuration errors. Strip brackets only when both opening and closing brackets are present.

Suggested patch
-	ipStr := strings.Trim(host, "[]")
+	ipStr := host
+	if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
+		ipStr = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
+	}
 	listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", net.JoinHostPort(ipStr, strconv.Itoa(port)))

Also, the first line of the comment at line 53 explains what the function does rather than why it checks port availability. Expand it to explain the purpose or rationale.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ipStr := strings.Trim(host, "[]")
listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", net.JoinHostPort(ipStr, strconv.Itoa(port)))
ipStr := host
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
ipStr = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
}
listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", net.JoinHostPort(ipStr, strconv.Itoa(port)))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/util/network.go` around lines 56 - 57, Replace the permissive
strings.Trim(host, "[]") with a guarded strip that only removes surrounding IPv6
brackets when both a leading '[' and trailing ']' exist: check host[0] == '['
and host[len-1] == ']' (and handle empty/short host safely), set ipStr =
host[1:len-1] in that case, otherwise leave host unchanged or return an error
for malformed bracket use; ensure this logic is applied before calling
(&net.ListenConfig{}).Listen(context.Background(), "tcp",
net.JoinHostPort(ipStr, strconv.Itoa(port))) so malformed inputs like "[::"
don't get silently normalized. Also update the explanatory comment above this
check to state why the function probes port availability (e.g., to detect
conflicts before binding or to choose an open port for downstream consumers),
rather than describing what the function does.

if err != nil {
return false
}
Expand Down
Loading