-
Notifications
You must be signed in to change notification settings - Fork 325
Description
Bug Description
The sort() method in pkg/interactive/autocomplete_suggestions.go has a data race when called concurrently from multiple goroutines. This can lead to data corruption or crashes during autocomplete initialization.
Location
File: pkg/interactive/autocomplete_suggestions.go
Lines: 23-39
Function: autoCompleteSuggestions.sort()
Issue
The sort() method modifies slices in place without any synchronization mechanism. When multiple goroutines call sort() (or initialiseSuggestions() which calls sort()), they race to read and write the same memory locations.
func (s *autoCompleteSuggestions) sort() {
sortSuggestions := func(suggestions []prompt.Suggest) {
sort.Slice(suggestions, func(i, j int) bool {
return suggestions[i].Text < suggestions[j].Text
// ^^^ DATA RACE: Concurrent reads/writes to suggestions slice
})
}
sortSuggestions(s.schemas)
sortSuggestions(s.unqualifiedTables)
// ... more sorts
}Impact
- Severity: Medium
- Symptoms: Data corruption, crashes, inconsistent autocomplete suggestions
- Conditions: Occurs when autocomplete is initialized from multiple goroutines simultaneously
- Race Detector Output:
WARNING: DATA RACE Read at 0x00c000820d20 by goroutine 27 Previous write at 0x00c000820d20 by goroutine 29
Steps to Reproduce
- Run the test with race detector:
go test -race ./pkg/interactive/ -run TestAutocompleteSuggestions_ConcurrentSort - Race detector reports data race
- Or, call
sort()from multiple goroutines:suggestions := newAutocompleteSuggestions() go suggestions.sort() go suggestions.sort() go suggestions.sort()
Detection
Found via concurrent access testing with Go's race detector:
- Test:
TestAutocompleteSuggestions_ConcurrentSort - File:
pkg/interactive/interactive_client_autocomplete_extended_test.go - Run with:
go test -race
Suggested Fixes
Option 1: Add Mutex Protection
type autoCompleteSuggestions struct {
mu sync.RWMutex
schemas []prompt.Suggest
unqualifiedTables []prompt.Suggest
// ... other fields
}
func (s *autoCompleteSuggestions) sort() {
s.mu.Lock()
defer s.mu.Unlock()
// ... existing sort logic
}Option 2: Document as Not Thread-Safe
If concurrent access is not expected in practice:
// sort sorts all suggestion lists alphabetically.
// NOTE: This method is NOT thread-safe. Callers must ensure
// exclusive access to the autoCompleteSuggestions instance.
func (s *autoCompleteSuggestions) sort() {
// ... existing logic
}Option 3: Make sort() Return New Slices
Instead of sorting in-place, return sorted copies:
func (s *autoCompleteSuggestions) sort() {
s.schemas = sortSuggestions(s.schemas)
s.unqualifiedTables = sortSuggestions(s.unqualifiedTables)
// ...
}
func sortSuggestions(suggestions []prompt.Suggest) []prompt.Suggest {
sorted := make([]prompt.Suggest, len(suggestions))
copy(sorted, suggestions)
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].Text < sorted[j].Text
})
return sorted
}Recommendation
Option 1 (Mutex Protection) is recommended if concurrent access is possible. Option 2 (Documentation) is acceptable if the current architecture guarantees single-threaded access.
Related
- Found during Wave 2 Core Functionality testing (Task 7: Autocomplete Tests)
- Part of bug hunting focus per Wave 2 Quality Override guidelines
- Detected using Go's race detector (
-raceflag)