Skip to content

Possible double-free / heap corruption in psqlODBC during SQLDisconnect cleanup #189

@cipriani-ivan

Description

@cipriani-ivan

Dear psqlODBC maintainers,
I would like to report a potential memory corruption issue in the PostgreSQL ODBC driver and ask whether this is a known or tracked problem.

Summary
We are observing repeatable heap corruption (0xC0000374) in a .NET application using:

PostgreSQL: 17.9
psqlODBC: 17.0.0.4
Windows: x64
Driver: PostgreSQL Unicode (x64)

The failure occurs during connection teardown after a failed connection.

Observed behavior
With Application Verifier + Page Heap, the crash consistently reports:
HEAP_CORRUPTION_ACTIONABLE_BlockNotBusy_DOUBLE_FREE

Stack trace
Below is the stack trace captured in WinDbg:
ucrtbase!free_base
psqlodbc35w!SC_clear_error
psqlodbc35w!PGAPI_FreeStmt
psqlodbc35w!SQLFreeStmt
odbc32!SQLDisconnect
System.Data.Odbc.OdbcConnection.Close()

This suggests a double free during statement/connection cleanup, likely in an error path.

Reproduction scenario
The issue appears under the following conditions:

Connection attempt fails (e.g. SQLSTATE 08S01, connection down)
Application immediately disposes the connection
Cleanup invokes SQLDisconnect / SQLFreeStmt
Occurs more frequently under:

Release builds
Parallel workloads
Forced cleanup paths

Analysis / suspicion

Multiple cleanup layers (SC_clear_error, PGAPI_FreeStmt) appear to release overlapping resources
The issue occurs in a failure path (connection already down)
Recent release notes do not indicate changes in this cleanup logic
Similar memory-safety fixes exist historically but not in this code path

Questions

Is this behavior a known issue in current psqlODBC versions?
Is there ongoing work related to cleanup safety in error paths?
Are there recommended usage constraints (threading / disposal patterns) to avoid this?

Context
This occurs in a modern multithreaded .NET application, where:

Failed connections are disposed immediately
Cleanup may occur under concurrency
Robust handling of failure paths is required

We understand the complexity of ODBC lifecycle semantics, but this appears to expose a double-free condition under certain cleanup scenarios.

Thank you for your time and for maintaining psqlODBC.
Best regards,
Ivan Cipriani

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions