Nil GlobalConfig causes panic in newRefreshConnectionState closes #4779 (#4899)

* Add test demonstrating nil GlobalConfig panic in newRefreshConnectionState

Test: TestRefreshConnectionState_ConnectionOrderEdgeCases
Demonstrates issue #4779 where nil GlobalConfig causes panic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add nil check for GlobalConfig in newRefreshConnectionState

Fixes #4779: nil GlobalConfig causes panic in newRefreshConnectionState

Changes:
- Add nil check for GlobalConfig in newRefreshConnectionState before SetUserSearchPath
- Add nil check in getDefaultSearchPath to handle nil GlobalConfig gracefully
- Test now passes instead of panicking with nil pointer dereference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Nathan Wallace
2025-11-17 03:57:59 -05:00
committed by GitHub
parent ea6a7a09cc
commit cea0a647cf
3 changed files with 50 additions and 3 deletions

View File

@@ -66,6 +66,12 @@ func newRefreshConnectionState(ctx context.Context, pluginManager pluginManager,
if pool == nil {
return nil, sperr.New("plugin manager returned nil pool")
}
// Check if GlobalConfig is initialized before proceeding
if steampipeconfig.GlobalConfig == nil {
return nil, sperr.New("GlobalConfig is not initialized")
}
// set user search path first
log.Printf("[INFO] setting up search path")
searchPath, err := db_local.SetUserSearchPath(ctx, pool)

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"sync"
"testing"
"time"
@@ -543,3 +544,39 @@ func TestNewRefreshConnectionState_NilPool(t *testing.T) {
t.Error("Expected error when pool is nil, got nil")
}
}
// TestRefreshConnectionState_ConnectionOrderEdgeCases tests edge cases in connection ordering
// This test demonstrates issue #4779 - nil GlobalConfig causes panic in newRefreshConnectionState
func TestRefreshConnectionState_ConnectionOrderEdgeCases(t *testing.T) {
t.Run("nil_global_config", func(t *testing.T) {
// ARRANGE: Save original GlobalConfig and set it to nil
originalConfig := steampipeconfig.GlobalConfig
steampipeconfig.GlobalConfig = nil
defer func() {
steampipeconfig.GlobalConfig = originalConfig
}()
ctx := context.Background()
// Create a mock plugin manager with a valid pool
// We need a pool to get past the nil pool check
// For this test, we can use a nil pool since we expect the function to fail
// before it tries to use the pool
mockPM := &mockPluginManager{
pool: &pgxpool.Pool{}, // Need a non-nil pool to get past line 66-68
}
// ACT: Call newRefreshConnectionState with nil GlobalConfig
// This should not panic - should return an error instead
_, err := newRefreshConnectionState(ctx, mockPM, nil)
// ASSERT: Should return an error, not panic
if err == nil {
t.Error("Expected error when GlobalConfig is nil, got nil")
}
if err != nil && !strings.Contains(err.Error(), "GlobalConfig") {
t.Errorf("Expected error message to mention GlobalConfig, got: %v", err)
}
})
}

View File

@@ -81,11 +81,15 @@ func SetUserSearchPath(ctx context.Context, pool *pgxpool.Pool) ([]string, error
func getDefaultSearchPath() []string {
// add all connections to the seatrch path (UNLESS ImportSchema is disabled)
var searchPath []string
// Check if GlobalConfig is initialized
if steampipeconfig.GlobalConfig != nil {
for connectionName, connection := range steampipeconfig.GlobalConfig.Connections {
if connection.ImportSchema == modconfig.ImportSchemaEnabled {
searchPath = append(searchPath, connectionName)
}
}
}
sort.Strings(searchPath)
// add the 'public' schema as the first schema in the search_path. This makes it