Fix #4783: Nil pointer dereference in updateConnectionSchema (#4901)

* Add test demonstrating bug #4783 - updateConnectionSchema with nil pool

This test verifies that updateConnectionSchema handles a nil pool gracefully.
While RefreshConnections (via newRefreshConnectionState) already checks for
nil pool since #4778, this test demonstrates that updateConnectionSchema
should perform an early nil check for better error handling.

The test currently passes because newRefreshConnectionState catches the nil
pool, but we should add an explicit check at the start of updateConnectionSchema
for clarity and to avoid unnecessary work.

Related to issue #4783

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

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

* Fix #4783: Add nil pool check in updateConnectionSchema

Add an early nil check for the pool at the beginning of updateConnectionSchema
to prevent unnecessary work and provide clearer error handling.

While newRefreshConnectionState (called by RefreshConnections) already checks
for nil pool since #4778, adding the check at the start of updateConnectionSchema
provides several benefits:

1. Avoids unnecessary work - we don't call RefreshConnections if pool is nil
2. Clearer error logging - warning message specifically indicates the issue
   is in updateConnectionSchema
3. Defense in depth - validates preconditions before executing the method

The method is called from the message server when a plugin sends a schema
update notification, so the nil check ensures we handle edge cases gracefully.

Closes #4783

🤖 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 04:00:18 -05:00
committed by GitHub
parent cea0a647cf
commit 55e2d407a0
2 changed files with 50 additions and 0 deletions

View File

@@ -319,3 +319,47 @@ func TestPluginMessageServer_StressConcurrentAccess(t *testing.T) {
close(stopCh)
wg.Wait()
}
// Test 18: UpdateConnectionSchema with Nil Pool
// Tests that updateConnectionSchema handles nil pool gracefully without panicking
// Issue #4783: The method calls RefreshConnections which accesses m.pool before the nil check
func TestPluginManager_UpdateConnectionSchema_NilPool(t *testing.T) {
// Create a PluginManager with a nil pool
pm := &PluginManager{
runningPluginMap: make(map[string]*runningPlugin),
pool: nil, // explicitly nil pool
}
ctx := context.Background()
// This should not panic - calling updateConnectionSchema with nil pool
// Previously this would panic because RefreshConnections accesses pool before nil check
pm.updateConnectionSchema(ctx, "test-connection")
// If we get here without panicking, the test passes
}
// Test 19: UpdateConnectionSchema with Nil Pool Concurrent
// Tests that concurrent calls to updateConnectionSchema with nil pool don't cause race conditions or panics
func TestPluginManager_UpdateConnectionSchema_NilPool_Concurrent(t *testing.T) {
pm := &PluginManager{
runningPluginMap: make(map[string]*runningPlugin),
pool: nil,
}
ctx := context.Background()
var wg sync.WaitGroup
numGoroutines := 10
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go func(idx int) {
defer wg.Done()
// Should not panic
pm.updateConnectionSchema(ctx, "test-connection")
}(i)
}
wg.Wait()
}

View File

@@ -796,6 +796,12 @@ func (m *PluginManager) setRateLimiters(pluginInstance string, pluginClient *sdk
func (m *PluginManager) updateConnectionSchema(ctx context.Context, connectionName string) {
log.Printf("[INFO] updateConnectionSchema connection %s", connectionName)
// check if pool is nil before attempting to refresh connections
if m.pool == nil {
log.Printf("[WARN] cannot update connection schema: pool is nil")
return
}
refreshResult := connection.RefreshConnections(ctx, m, connectionName)
if refreshResult.Error != nil {
log.Printf("[TRACE] error refreshing connections: %s", refreshResult.Error)