Message-ID: From: "jarvis24young (@jarvis24young)" To: "postgresql-interfaces/psqlodbc" Date: Thu, 07 May 2026 02:00:45 +0000 Subject: [postgresql-interfaces/psqlodbc] PR #183: Detach freed app descriptors from statements List-Id: X-GitHub-Author-Id: 48787405 X-GitHub-Author-Login: jarvis24young X-GitHub-Issue: 183 X-GitHub-Repo: postgresql-interfaces/psqlodbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/postgresql-interfaces/psqlodbc/pull/183 Content-Type: text/plain; charset=utf-8 Fix a dangling application descriptor reference left on statements after SQLFreeHandle(SQL_HANDLE_DESC). When an application descriptor is attached through SQL_ATTR_APP_ROW_DESC or SQL_ATTR_APP_PARAM_DESC, the statement stores the descriptor pointer directly. PGAPI_FreeDesc() removed and freed the descriptor from the connection descriptor list, but did not reset statements still pointing at it. A later statement attribute write through SC_get_ARDF()/SC_get_APDF() can therefore access freed memory. The fix detaches a non-embedded descriptor from all statements on the same connection before destroying it. Statements are reset to their implicit ARD/APD. The new regression test covers both descriptor classes: - attach an application row descriptor, free it, then set SQL_ATTR_ROW_ARRAY_SIZE - attach an application parameter descriptor, free it, then set SQL_ATTR_PARAMSET_SIZE - verify SQLGetStmtAttr no longer returns the freed descriptor handle Verification performed in WSL with ASan/UBSan: ```text # vulnerable build, minimal public-API reproducer ERROR: AddressSanitizer: heap-use-after-free WRITE of size 8 #0 PGAPI_SetStmtAttr pgapi30.c:2491 #1 SQLSetStmtAttr odbcapi30.c:698 freed by: #1 PGAPI_FreeDesc descriptor.c:442 #2 SQLFreeHandle odbcapi30.c:291 ``` After this patch, from a clean clone of this branch: ```text ./bootstrap ./configure --with-unixodbc=__without_odbc_config \ CFLAGS='-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined -I/usr/include/postgresql -DSQLCOLATTRIBUTE_SQLLEN -Wall' \ LDFLAGS='-fsanitize=address,undefined' make -j2 cd test make exe/descriptors-free-test LIBODBC=-lodbc ASAN_OPTIONS=detect_leaks=0:halt_on_error=1:abort_on_error=1 \ UBSAN_OPTIONS=halt_on_error=1 \ ODBCSYSINI=. ODBCINSTINI=./odbcinst.ini ODBCINI=./odbc.ini \ ./exe/descriptors-free-test ``` Result: ```text connected freeing attached application row descriptor freeing attached application parameter descriptor disconnecting ```