From 858e2bc8ecde70b704173d28993a977410136dab Mon Sep 17 00:00:00 2001
From: shruthi gowda <shruthi.kc@enterprisedb.com>
Date: Wed, 15 Apr 2026 08:34:18 +0000
Subject: [PATCH v5] Add missing connection validation in ECPG

ECPGdeallocate_all(), ECPGprepared_statement(), ECPGget_desc(), and
ecpg_freeStmtCacheEntry() could crash or misbehave when operating on
NULL or invalid connections. Add proper connection validation to
prevent dereferencing NULL pointers.
---
 src/interfaces/ecpg/ecpglib/descriptor.c | 12 ++++++++++--
 src/interfaces/ecpg/ecpglib/prepare.c    | 25 ++++++++++++++++--------
 2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 39cd5130ec9..1ad5f2d88cc 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -476,6 +476,16 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
 		memset(&stmt, 0, sizeof stmt);
 		stmt.lineno = lineno;
 
+		/* desperate try to guess something sensible */
+		stmt.connection = ecpg_get_connection(NULL);
+		if (stmt.connection == NULL)
+		{
+			ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
+					   ecpg_gettext("NULL"));
+			va_end(args);
+			return false;
+		}
+
 		/* Make sure we do NOT honor the locale for numeric input */
 		/* since the database gives the standard decimal point */
 		/* (see comments in execute.c) */
@@ -505,8 +515,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
 		setlocale(LC_NUMERIC, "C");
 #endif
 
-		/* desperate try to guess something sensible */
-		stmt.connection = ecpg_get_connection(NULL);
 		ecpg_store_result(ECPGresult, index, &stmt, &data_var);
 
 #ifdef HAVE_USELOCALE
diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c
index 5c7c5397535..f9489044724 100644
--- a/src/interfaces/ecpg/ecpglib/prepare.c
+++ b/src/interfaces/ecpg/ecpglib/prepare.c
@@ -381,8 +381,12 @@ ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
 bool
 ECPGdeallocate_all(int lineno, int compat, const char *connection_name)
 {
-	return ecpg_deallocate_all_conn(lineno, compat,
-									ecpg_get_connection(connection_name));
+	struct connection *con = ecpg_get_connection(connection_name);
+
+	if (!ecpg_init(con, connection_name, lineno))
+		return false;
+
+	return ecpg_deallocate_all_conn(lineno, compat, con);
 }
 
 char *
@@ -395,13 +399,15 @@ ecpg_prepared(const char *name, struct connection *con)
 }
 
 /* return the prepared statement */
-/* lineno is not used here, but kept in to not break API */
 char *
 ECPGprepared_statement(const char *connection_name, const char *name, int lineno)
 {
-	(void) lineno;				/* keep the compiler quiet */
+	struct connection *con = ecpg_get_connection(connection_name);
+
+	if (!ecpg_init(con, connection_name, lineno))
+		return NULL;
 
-	return ecpg_prepared(name, ecpg_get_connection(connection_name));
+	return ecpg_prepared(name, con);
 }
 
 /*
@@ -499,9 +505,12 @@ ecpg_freeStmtCacheEntry(int lineno, int compat,
 	con = ecpg_get_connection(entry->connection);
 
 	/* free the 'prepared_statement' list entry */
-	this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
-	if (this && !deallocate_one(lineno, compat, con, prev, this))
-		return -1;
+	if (con)
+	{
+		this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
+		if (this && !deallocate_one(lineno, compat, con, prev, this))
+			return -1;
+	}
 
 	entry->stmtID[0] = '\0';
 
-- 
2.43.0

