mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-11-14 16:07:25 +00:00
psqlodbc: patch CVE-2026-109448
Backport the commit identified by Debian[1] Details: https://nvd.nist.gov/vuln/detail/cve-2026-109448 [1]https://security-tracker.debian.org/tracker/CVE-2026-109448 PTEST pass: root@qemuarm64:~# ptest-runner psqlodbc START: ptest-runner 2026-10-17T09:22 BEGIN: /usr/lib/psqlodbc/ptest ... DURATION: 43 END: /usr/lib/psqlodbc/ptest 2026-10-17T09:23 STOP: ptest-runner TOTAL: 1 FAIL: 0 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
This commit is contained in:
1 parent
622cd276dd
commit
3e0c7af047
2 files changed
+244
No files matched your search
@@ -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 \
|
||||
@@ -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 \
|
||||
"
|
||||
|
||||
|
||||
Reference in new issue
Block a user