Skip to content

Segfault when binding array parameter via Dapper ICustomQueryParameter #2189

Description

@elsand

Full repro

See https://github.com/elsand/npgsql-dapper-segfault/. The relevant code can also be found below.

Summary

A simple Dapper + Npgsql program crashes the process when binding an array parameter via ICustomQueryParameter and running SELECT unnest(@Ids). This happens on macOS (SIGSEGV, exit 139) and Windows (Fatal error. Internal CLR error 0x80131506). The repro targets net9.0 and net10.0 and uses Npgsql 10.0.1 + Dapper 2.1.66.

Crash seems to occur during Dapper parameter setup (before query execution) when NpgsqlParameter is created for an array via ICustomQueryParameter.

(Moved from npgsql/npgsql#6434, as this does not appear to be a npgsql-issue after all. Not sure if it's Dapper either, or if this belongs to dotnet/runtime).

Steps

  1. git clone https://github.com/elsand/npgsql-dapper-segfault/
  2. set PG_CONNECTION_STRING to a PostgreSQL instance
  3. dotnet run -f net10.0 (or -f net9.0)

Expected

Query returns the unnest’ed values.

Actual

Process crashes. On macOS it’s a SIGSEGV (exit 139). On Windows, it reports “Fatal error. Internal CLR error. (0x80131506)”.

Running on Mac gives no console output, unless minidumps are enabled:

DOTNET_DbgEnableMiniDump=1 \
DOTNET_DbgMiniDumpType=3 \
DOTNET_DbgMiniDumpName=/tmp/npgsql_segfault_%p.dmp \
PG_CONNECTION_STRING='Host=localhost;Database=postgres;Username=postgres;Password=xxxxxx' \
dotnet run -f net10.0
[createdump] Gathering state for process 51920 [createdump] Crashing thread 131147a signal 11 (000b)
[createdump] Writing triage minidump to file /tmp/npgsql_segfault_51920.dmp
[createdump] Written 38621464 bytes (2357 pages) to core file
[createdump] Target process is alive
[createdump] Dump successfully written in 197ms

Minidump can be provided upon request.

Running on Windows gives substantially more output:

PS C:\Users\bjorn\Repos\npgsql-dapper-segfault> dotnet run -f net10.0
Fatal error.
Internal CLR error. (0x80131506)
at Dapper.CommandDefinition.SetupCommand(System.Data.IDbConnection, System.Action`2<System.Data.IDbCommand,System.Object>)
at Dapper.SqlMapper.TrySetupAsyncCommand(Dapper.CommandDefinition, System.Data.IDbConnection, System.Action`2<System.Data.IDbCommand,System.Object>)
at Dapper.SqlMapper+<QueryAsync>d__33`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[Dapper.SqlMapper+<QueryAsync>d__33`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Dapper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null]](<QueryAsync>d__33`1<System.__Canon> ByRef)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Start[[Dapper.SqlMapper+<QueryAsync>d__33`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Dapper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null]](<QueryAsync>d__33`1<System.__Canon> ByRef)
at Dapper.SqlMapper.QueryAsync[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Data.IDbConnection, System.Type, Dapper.CommandDefinition)
at Dapper.SqlMapper.QueryAsync[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Data.IDbConnection, Dapper.CommandDefinition)
at Program+<<Main>$>d__0.MoveNext()
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext(System.Threading.Thread)
at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
at System.Threading.Tasks.Task.RunContinuations(System.Object)
at System.Threading.Tasks.Task`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TrySetResult(System.Threading.Tasks.VoidTaskResult)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetExistingTaskResult(System.Threading.Tasks.Task`1<System.Threading.Tasks.VoidTaskResult>, System.Threading.Tasks.VoidTaskResult)
at Npgsql.NpgsqlConnection+<<Open>g__OpenAsync|42_0>d.MoveNext()
(rest of output omitted)

Full output of Windows run

Environment

  • Hardware: Apple M3 Pro / AMD Ryzen 7 3700X
  • OS: macOS 26.2 (Build 25C56) / Windows 11 Pro (Build 26200.7623)
  • PostgreSQL: 16.10
  • SDKs tested: .NET 9.0.310, .NET 10.0.102
  • Packages: Npgsql 10.0.1, Dapper 2.1.66

Relevant code

usingSystem.Data;usingDapper;usingNpgsql;awaitusingvarconnection=newNpgsqlConnection(Environment.GetEnvironmentVariable("PG_CONNECTION_STRING")??"Host=localhost;Database=postgres;Username=postgres;Password=postgres");awaitconnection.OpenAsync();varparameters=new{Ids=newPostgresArray<string>(["a"])// Also tested with `int` and `Guid` type parameters - same result};varcommand=newCommandDefinition("SELECT unnest(@Ids) AS Value",parameters,cancellationToken:CancellationToken.None);varrows=awaitconnection.QueryAsync<string>(command);// <--- Segfault happens hereforeach(varvalueinrows)// <--- This line is never reached{Console.WriteLine(value);}internalreadonlystructPostgresArray<T>(T[]value):SqlMapper.ICustomQueryParameter{publicvoidAddParameter(IDbCommandcommand,stringname){varparam=newNpgsqlParameter(name,value);command.Parameters.Add(param);}}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions