Nil pool validation in newRefreshConnectionState closes #4778 (#4825)

* Add test demonstrating bug #4778 - nil pool causes panic

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

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

* Fix #4778: Add nil pool validation in newRefreshConnectionState

Add nil check immediately after retrieving pool from pluginManager
to prevent panic when pool is nil. This addresses the issue where
a nil pool would cause a segmentation fault when passed to
db_local.SetUserSearchPath().

The fix returns a descriptive error instead of panicking, allowing
calling code to handle the error gracefully.

🤖 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-15 19:11:10 -05:00
committed by GitHub
parent 8915b7598b
commit 6f5b471fe0
2 changed files with 67 additions and 0 deletions

View File

@@ -63,6 +63,9 @@ func newRefreshConnectionState(ctx context.Context, pluginManager pluginManager,
defer log.Println("[DEBUG] newRefreshConnectionState end")
pool := pluginManager.Pool()
if pool == nil {
return nil, sperr.New("plugin manager returned nil pool")
}
// set user search path first
log.Printf("[INFO] setting up search path")
searchPath, err := db_local.SetUserSearchPath(ctx, pool)

View File

@@ -8,6 +8,11 @@ import (
"testing"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/turbot/pipe-fittings/v2/error_helpers"
"github.com/turbot/pipe-fittings/v2/plugin"
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
"github.com/turbot/steampipe/v2/pkg/pluginmanager_service/grpc/shared"
"github.com/turbot/steampipe/v2/pkg/steampipeconfig"
)
@@ -479,3 +484,62 @@ func TestConnectionError(t *testing.T) {
t.Error("Error not preserved")
}
}
// mockPluginManager is a mock implementation of pluginManager interface for testing
type mockPluginManager struct {
shared.PluginManager
pool *pgxpool.Pool
}
func (m *mockPluginManager) Pool() *pgxpool.Pool {
return m.pool
}
// Implement other required methods from pluginManager interface
func (m *mockPluginManager) OnConnectionConfigChanged(context.Context, ConnectionConfigMap, map[string]*plugin.Plugin) {
}
func (m *mockPluginManager) GetConnectionConfig() ConnectionConfigMap {
return nil
}
func (m *mockPluginManager) HandlePluginLimiterChanges(PluginLimiterMap) error {
return nil
}
func (m *mockPluginManager) ShouldFetchRateLimiterDefs() bool {
return false
}
func (m *mockPluginManager) LoadPluginRateLimiters(map[string]string) (PluginLimiterMap, error) {
return nil, nil
}
func (m *mockPluginManager) SendPostgresSchemaNotification(context.Context) error {
return nil
}
func (m *mockPluginManager) SendPostgresErrorsAndWarningsNotification(context.Context, error_helpers.ErrorAndWarnings) {
}
func (m *mockPluginManager) UpdatePluginColumnsTable(context.Context, map[string]*proto.Schema, []string) error {
return nil
}
// TestNewRefreshConnectionState_NilPool tests that newRefreshConnectionState handles nil pool gracefully
// This test demonstrates issue #4778 - nil pool from pluginManager causes panic
func TestNewRefreshConnectionState_NilPool(t *testing.T) {
ctx := context.Background()
// Create a mock plugin manager that returns nil pool
mockPM := &mockPluginManager{
pool: nil,
}
// This should not panic - should return an error instead
_, err := newRefreshConnectionState(ctx, mockPM, []string{})
if err == nil {
t.Error("Expected error when pool is nil, got nil")
}
}