#1152614 libiodbc2: segfault on first SQLAllocHandle, -std=c17 hides strdup() prototype and truncates pointers

Package:
libiodbc2
Source:
libiodbc2
Description:
iODBC Driver Manager
Submitter:
Markus Klein
Date:
2026-10-30 15:43:02 UTC
Severity:
normal
Tags:
#1152614#5
Date:
2026-10-30 15:41:36 UTC
From:
To:
Dear Maintainer,


I am the maintainer of the `odbc-sys` Rust crate. After updating the
runners of the GitHub workflow to Ubuntu 26.04 my tests against iodbc
started failing. I told Claude to investigate the issue and it found
that the package should be build with -std=gnu17 rather than -std=c17.

Underneath the detailed root cause analysis as generated by claude
---

Since 3.52.16-1, every program linked against libiodbc2 segfaults on its
first ODBC call, allocating an environment handle with SQLAllocHandle. I
reproduced this on Ubuntu 26.04 ("resolute"), which ships 3.52.16-2
unchanged from Debian. 3.52.9-4 (Ubuntu 24.04) works fine with the same
program.

Cause
-----

3.52.16-1 started building with -std=c17 (#1097202). That is strict ISO C,
so glibc's <string.h> does not declare POSIX functions such as strdup()
and strcasecmp(). debian/rules also passes

   -Wno-implicit-function-declaration -Wno-int-conversion
   -Wno-incompatible-pointer-types

which hides the resulting diagnostics. Without these flags the build fails:

   ../include/iodbc.h:116:34: error: implicit declaration of function
'strdup' [-Wimplicit-function-declaration]
   SQLGetInstalledDrivers.c:104:10: error: implicit declaration of
function 'strcasecmp' [-Wimplicit-function-declaration]
   SQLGetInstalledDrivers.c:167:31: error: assignment to 'void *' from
'int' makes pointer from integer without a cast [-Wint-conversion]

Because strdup() is implicitly declared as returning int, the returned
64-bit pointer is truncated to 32 bits. In _iodbcdm_cfg_init()
(iodbcinst/inifile.c), pconfig->fileName = STRDUP(filename) stores such
a truncated pointer, and _iodbcdm_cfg_done() then calls free() on it.
This happens while the environment handle is allocated, when the driver
manager reads "AppUnicodeType" from odbcinst.ini, so every application
crashes.

Backtrace from a -g -O0 build using the flags from debian/rules (note the
32-bit value passed to free()):

   Program received signal SIGSEGV, Segmentation fault.
   #0  __GI___libc_free (mem=0x6f63e0e0) at ./malloc/malloc.c:3333
   #1  _iodbcdm_cfg_done (pconfig=0x5fe96f63e070) at inifile.c:182
   #2  _iodbcdm_cfg_init (ppconf=..., filename="/etc/odbcinst.ini",
doCreate=0) at inifile.c:163
   #3  _iodbcdm_cfg_search_init (ppconf=..., filename="odbcinst.ini",
doCreate=0) at inifile.c:1262
   #4  GetPrivateProfileString (lpszSection="ODBC",
lpszEntry="AppUnicodeType", ...) at SQLGetPrivateProfileString.c:98

Reproducer
----------

   $ cat t.c
   #include <stdio.h>
   #include <sql.h>
   #include <sqlext.h>
   int main(void) {
     SQLHANDLE env, dbc;
     SQLRETURN r;
     r = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
printf("env %d\n", r);
     r = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
     r = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); printf("dbc %d\n", r);
     SQLFreeHandle(SQL_HANDLE_DBC, dbc);
     SQLFreeHandle(SQL_HANDLE_ENV, env);
     puts("ok");
     return 0;
   }
   $ gcc t.c -I/usr/include/iodbc -liodbc -o t && ./t
   Segmentation fault (core dumped)

No odbc.ini or odbcinst.ini needs to exist.

Fix
---

Build with -std=gnu17 instead of -std=c17. This still avoids the C23
issues from #1097202 (the old-style "()" function pointer declarations),
but keeps the POSIX/GNU declarations visible. With -std=gnu17 the
upstream sources compiled cleanly with GCC 15.2.0 even without the three
-Wno-* flags, and the reproducer above runs successfully (env 0, dbc 0,
ok). I would suggest dropping those flags as well, so that problems like
this one fail the build again:
--- a/debian/rules +++ b/debian/rules @@ -export CFLAGS += -std=c17 -Wno-implicit-function-declaration -Wno-int-conversion -Wno-incompatible-pointer-types +export CFLAGS += -std=gnu17 I tested this with the upstream configure/make on the 3.52.16-2 source, not with a full dpkg-buildpackage run. Environment where it was reproduced: Ubuntu 26.04 (Docker image ubuntu:26.04), libiodbc2 3.52.16-2, gcc 15.2.0, x86_64. Found via the CI of the Rust crate odbc-sys: https://github.com/pacman82/odbc-sys/actions/runs/41037444708/job/124001751617 Regards, Markus Klein