postgresql-interfaces/psqlodbc GitHub issues and pull requests (mirror)
help / color / mirror / Atom feedFrom: jarvis24young (@jarvis24young) <[email protected]>
To: postgresql-interfaces/psqlodbc <[email protected]>
Subject: [postgresql-interfaces/psqlodbc] issue #177: OOM: SQLAllocHandle(SQL_HANDLE_STMT) can segfault if ARD_AllocBookmark malloc fails
Date: Sat, 25 Apr 2026 04:01:49 +0000
Message-ID: <[email protected]> (raw)
# OOM: SQLAllocHandle(SQL_HANDLE_STMT) can segfault if ARD_AllocBookmark malloc fails
## Summary
While doing defensive robustness testing of psqlODBC, I found a NULL-dereference crash on the statement allocation path when an internal bookmark allocation fails.
This is an OOM/robustness issue. I am not claiming a practical remote exploit; the reproducer uses malloc-failure injection to force the allocation failure deterministically. The expected behavior would be to return an ODBC error/diagnostic instead of crashing the hosting process.
## Affected path
`SQLAllocHandle(SQL_HANDLE_STMT, ...)` reaches `PGAPI_AllocStmt()`, which calls `ARD_AllocBookmark()`:
```c
BindInfoClass *
ARD_AllocBookmark(ARDFields *ardopts)
{
if (!ardopts->bookmark)
{
ardopts->bookmark = (BindInfoClass *) malloc(sizeof(BindInfoClass));
pg_memset(ardopts->bookmark, 0, sizeof(BindInfoClass));
}
return ardopts->bookmark;
}
```
If `malloc(sizeof(BindInfoClass))` returns `NULL`, `pg_memset()` is called with a NULL pointer.
Observed call chain:
```text
SQLAllocHandle(SQL_HANDLE_STMT)
-> PGAPI_AllocStmt statement.c:232
-> ARD_AllocBookmark descriptor.c:345
-> malloc(sizeof(BindInfoClass)) returns NULL
-> pg_memset(NULL, ...)
```
On my x86_64 Linux build, `sizeof(BindInfoClass)` was 40 bytes.
## Reproducer
Environment used:
- Linux under WSL2
- unixODBC
- PostgreSQL test database
- psqlODBC built with debug/gcov flags, no ASan for this OOM injection run
A minimal black-box test only uses public ODBC APIs:
```c
SQLDriverConnect(...);
SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
```
I forced the relevant allocation to fail with an `LD_PRELOAD` malloc shim that returns `NULL` on the Nth 40-byte allocation:
```bash
PODBC_FAIL_MALLOC_SIZE=40 PODBC_FAIL_MALLOC_N=178 \
LD_PRELOAD=./exe/malloc_fail_shim.so \
ODBCSYSINI=. ODBCINSTINI=./odbcinst.ini ODBCINI=./odbc.ini \
./exe/ard-bookmark-oom-bugwatch-test
```
Observed output:
```text
connected
allocating statement handle through SQLAllocHandle(SQL_HANDLE_STMT)
malloc-fail-shim: failing malloc(40) occurrence 178
../.libs/psqlodbcw.so(+0x8f5e9)
../.libs/psqlodbcw.so(+0x7cea0)
../.libs/psqlodbcw.so(SQLAllocHandle+0x20e)
oom_rc=139
```
Address mapping:
```text
driver +0x8f5e9:
ARD_AllocBookmark
.../descriptor.c:345
driver +0x7cea0:
PGAPI_AllocStmt
.../statement.c:232
```
Normal run without malloc failure completes successfully:
```text
connected
allocating statement handle through SQLAllocHandle(SQL_HANDLE_STMT)
SQLAllocHandle stmt rc=0 hstmt=...
disconnecting
statement allocation completed without crashing
```
## Expected behavior
If bookmark allocation fails during statement allocation, the driver should return an ODBC error, ideally with a memory-allocation diagnostic, rather than dereferencing NULL and crashing.
## Suggested fix direction
`ARD_AllocBookmark()` could return `NULL` when allocation fails, and callers that require the bookmark should handle that by setting an appropriate diagnostic and returning `SQL_ERROR`.
Known direct callers worth checking:
- `statement.c::PGAPI_AllocStmt()`
- `bind.c::PGAPI_BindCol()`
- `descriptor.c::ARDFields_copy()`
I can provide the regression test and malloc-failure shim if that would be useful.
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: github://postgresql-interfaces/psqlodbc
Cc: [email protected], [email protected]
Subject: Re: [postgresql-interfaces/psqlodbc] issue #177: OOM: SQLAllocHandle(SQL_HANDLE_STMT) can segfault if ARD_AllocBookmark malloc fails
In-Reply-To: <<[email protected]>>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox