diff --git a/meta-oe/recipes-dbs/psqlodbc/files/CVE-2026-109448.patch b/meta-oe/recipes-dbs/psqlodbc/files/CVE-2026-109448.patch
new file mode 100644
index 0000000000..12f6cdd1d8
--- /dev/null
+++ b/meta-oe/recipes-dbs/psqlodbc/files/CVE-2026-109448.patch
@@ -0,0 +1,243 @@
+From 5c9443fb0c8c0e263e1f8d0298987e91c4f5ccea Mon Sep 17 00:00:00 2001
+From: Dave Cramer <davecramer@gmail.com>
+Date: Mon, 12 Oct 2026 11:47:08 -0400
+Subject: [PATCH] Merge commit from fork
+
+The APD, IPD and put-data binding counts are SQLSMALLINT.  Binding
+parameter 32768 wrapped the count to -32768, so execution failed with
+07002 even though every parameter was bound; binding parameter 32769
+then extended the arrays with a memset starting at index -32768,
+writing zeros up to 1.25 MiB before the start of the APD array (and
+likewise for the IPD and put-data arrays), which corrupts the heap.
+
+SQLNumParams and SQL_DESC_COUNT are SQLSMALLINT too, so 32767 is the
+largest parameter count ODBC can describe.  PGAPI_BindParameter now
+returns 07009 for parameter numbers outside 1..32767, which also covers
+parameter number 0 for applications that call the driver without a
+driver manager.
+
+New param-count-limit test binds 32767, 32768 and 32769 parameters.
+
+Assisted-By: Claude
+(cherry picked from commit 86e4418e9553aa0891315db7531f8cd31eb1575e)
+
+CVE: CVE-2026-109448
+Upstream-Status: Backport [https://github.com/postgresql-interfaces/psqlodbc/commit/86e4418e9553aa0891315db7531f8cd31eb1575e]
+Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
+---
+ bind.c                              |  12 +++
+ test/expected/param-count-limit.out |  12 +++
+ test/src/param-count-limit-test.c   | 142 ++++++++++++++++++++++++++++
+ test/tests                          |   1 +
+ 4 files changed, 167 insertions(+)
+ create mode 100644 test/expected/param-count-limit.out
+ create mode 100644 test/src/param-count-limit-test.c
+
+diff --git a/bind.c b/bind.c
+index 3b566ec..b3e5ca3 100644
+--- a/bind.c
++++ b/bind.c
+@@ -16,6 +16,7 @@
+ /* #include <stdlib.h> */
+ #include <string.h>
+ #include <ctype.h>
++#include <limits.h>
+ #include "bind.h"
+ #include "misc.h"
+ 
+@@ -57,6 +58,17 @@ PGAPI_BindParameter(HSTMT hstmt,
+ 	}
+ 	SC_clear_error(stmt);
+ 
++	/*
++	 * The APD, IPD and put-data counts are SQLSMALLINT, like SQLNumParams
++	 * and SQL_DESC_COUNT, so a larger parameter number would wrap the count
++	 * negative and the next binding would write before the bindings array.
++	 */
++	if (ipar < 1 || ipar > SHRT_MAX)
++	{
++		SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_BindParameter.", func);
++		return SQL_ERROR;
++	}
++
+ 	apdopts = SC_get_APDF(stmt);
+ 	if (apdopts->allocated < ipar)
+ 		extend_parameter_bindings(apdopts, ipar);
+diff --git a/test/expected/param-count-limit.out b/test/expected/param-count-limit.out
+new file mode 100644
+index 0000000..623bcbf
+--- /dev/null
++++ b/test/expected/param-count-limit.out
+@@ -0,0 +1,12 @@
++connected
++APD SQL_DESC_COUNT=-1: error SQLSTATE=07009
++APD bind 1 after SQL_DESC_COUNT=-1: ok
++IPD SQL_DESC_COUNT=-1: error SQLSTATE=07009
++IPD bind 1 after SQL_DESC_COUNT=-1: ok
++bind 0: error SQLSTATE=07009
++32767 params, bind 32767: ok
++32767 params, execute: ok
++32767 params, result 1
++32768 params, bind 32768: error SQLSTATE=07009
++32769 params, bind 32768: error SQLSTATE=07009
++disconnecting
+diff --git a/test/src/param-count-limit-test.c b/test/src/param-count-limit-test.c
+new file mode 100644
+index 0000000..e9554cd
+--- /dev/null
++++ b/test/src/param-count-limit-test.c
+@@ -0,0 +1,142 @@
++/*
++ * Test the limits on parameter numbers and descriptor counts.  The driver
++ * keeps parameter binding counts in SQLSMALLINT, so SQLBindParameter with a
++ * parameter number above 32767, or SQL_DESC_COUNT set negative, used to
++ * wrap the count negative and make the next binding write zeros before the
++ * start of the bindings array.
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "common.h"
++
++#define MAX_PARAMS	32767
++
++static void
++print_state(const char *what, SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE h)
++{
++	SQLCHAR		state[6] = "";
++	SQLINTEGER	native;
++	SQLCHAR		msg[256];
++	SQLSMALLINT	len;
++
++	printf("%s: ", what);
++	if (SQL_SUCCEEDED(rc))
++	{
++		printf("ok\n");
++		return;
++	}
++	SQLGetDiagRec(htype, h, 1, state, &native, msg, sizeof(msg), &len);
++	printf("error SQLSTATE=%s\n", (char *) state);
++}
++
++/* SELECT 1 WHERE 1 IN (?, ?, ..., ?) with nparams markers, all bound to 1 */
++static void
++run_with_params(int nparams)
++{
++	SQLRETURN	rc;
++	HSTMT		hstmt = SQL_NULL_HSTMT;
++	SQLINTEGER	one = 1;
++	SQLINTEGER	result = 0;
++	char	   *sql, *p;
++	char		what[64];
++	int			i;
++
++	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
++	CHECK_CONN_RESULT(rc, "SQLAllocHandle failed", conn);
++
++	sql = malloc(32 + 2 * nparams);
++	p = sql + sprintf(sql, "SELECT 1 WHERE 1 IN (");
++	for (i = 0; i < nparams; i++)
++	{
++		if (i > 0)
++			*p++ = ',';
++		*p++ = '?';
++	}
++	strcpy(p, ")");
++
++	for (i = 1; i <= nparams; i++)
++	{
++		rc = SQLBindParameter(hstmt, (SQLUSMALLINT) i, SQL_PARAM_INPUT,
++							  SQL_C_SLONG, SQL_INTEGER, 0, 0, &one, 0, NULL);
++		if (!SQL_SUCCEEDED(rc))
++			break;
++	}
++	snprintf(what, sizeof(what), "%d params, bind %d", nparams, i <= nparams ? i : nparams);
++	print_state(what, rc, SQL_HANDLE_STMT, hstmt);
++
++	if (SQL_SUCCEEDED(rc))
++	{
++		rc = SQLExecDirect(hstmt, (SQLCHAR *) sql, SQL_NTS);
++		snprintf(what, sizeof(what), "%d params, execute", nparams);
++		print_state(what, rc, SQL_HANDLE_STMT, hstmt);
++	}
++	if (SQL_SUCCEEDED(rc))
++	{
++		rc = SQLBindCol(hstmt, 1, SQL_C_SLONG, &result, 0, NULL);
++		CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt);
++		rc = SQLFetch(hstmt);
++		CHECK_STMT_RESULT(rc, "SQLFetch failed", hstmt);
++		printf("%d params, result %d\n", nparams, (int) result);
++	}
++
++	free(sql);
++	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
++}
++
++/* Set SQL_DESC_COUNT of the statement's APD or IPD to -1, then bind */
++static void
++negative_desc_count(SQLINTEGER desc_attr, const char *desc_name)
++{
++	SQLRETURN	rc;
++	HSTMT		hstmt = SQL_NULL_HSTMT;
++	SQLHDESC	hdesc;
++	SQLINTEGER	one = 1;
++	char		what[64];
++
++	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
++	CHECK_CONN_RESULT(rc, "SQLAllocHandle failed", conn);
++
++	rc = SQLGetStmtAttr(hstmt, desc_attr, &hdesc, 0, NULL);
++	CHECK_STMT_RESULT(rc, "SQLGetStmtAttr failed", hstmt);
++
++	rc = SQLSetDescField(hdesc, 0, SQL_DESC_COUNT, (SQLPOINTER) (SQLLEN) -1, 0);
++	snprintf(what, sizeof(what), "%s SQL_DESC_COUNT=-1", desc_name);
++	print_state(what, rc, SQL_HANDLE_DESC, hdesc);
++
++	rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
++						  SQL_INTEGER, 0, 0, &one, 0, NULL);
++	snprintf(what, sizeof(what), "%s bind 1 after SQL_DESC_COUNT=-1", desc_name);
++	print_state(what, rc, SQL_HANDLE_STMT, hstmt);
++
++	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
++}
++
++int
++main(int argc, char **argv)
++{
++	SQLRETURN	rc;
++	HSTMT		hstmt = SQL_NULL_HSTMT;
++	SQLINTEGER	one = 1;
++
++	test_connect();
++
++	negative_desc_count(SQL_ATTR_APP_PARAM_DESC, "APD");
++	negative_desc_count(SQL_ATTR_IMP_PARAM_DESC, "IPD");
++
++	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
++	CHECK_CONN_RESULT(rc, "SQLAllocHandle failed", conn);
++	rc = SQLBindParameter(hstmt, 0, SQL_PARAM_INPUT, SQL_C_SLONG,
++						  SQL_INTEGER, 0, 0, &one, 0, NULL);
++	print_state("bind 0", rc, SQL_HANDLE_STMT, hstmt);
++	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
++
++	run_with_params(MAX_PARAMS);
++	run_with_params(MAX_PARAMS + 1);
++	run_with_params(MAX_PARAMS + 2);
++
++	test_disconnect();
++
++	return 0;
++}
+diff --git a/test/tests b/test/tests
+index 5074bca..c8af1ab 100644
+--- a/test/tests
++++ b/test/tests
+@@ -63,6 +63,7 @@ TESTBINS = exe/connect-test \
+ 	exe/descriptors-free-test \
+ 	exe/primarykeys-include-test \
+ 	exe/interval-overflow-test \
++	exe/param-count-limit-test \
+ 	exe/conn-settings-test \
+ 	exe/percent-decode-test \
+ 	exe/dbms-version-test \
diff --git a/meta-oe/recipes-dbs/psqlodbc/psqlodbc_18.00.0002.bb b/meta-oe/recipes-dbs/psqlodbc/psqlodbc_18.00.0002.bb
index ae1d603e1d..9756bcfad2 100644
--- a/meta-oe/recipes-dbs/psqlodbc/psqlodbc_18.00.0002.bb
+++ b/meta-oe/recipes-dbs/psqlodbc/psqlodbc_18.00.0002.bb
@@ -23,6 +23,7 @@ SRC_URI = "git://github.com/postgresql-interfaces/psqlodbc.git;protocol=https;br
            file://psqlodbc-remove-some-checks-for-cross-compiling.patch \
            file://psqlodbc-donot-use-the-hardcode-libdir.patch \
            file://psqlodbc-fix-for-ptest-support.patch \
+           file://CVE-2026-109448.patch \
            file://run-ptest \
            "
 
