From e355992ff96fa0aa9ea2a68209a59c05c048e751 Mon Sep 17 00:00:00 2001
From: Hiroshi Inoue <inoue@tpf.co.jp>
Date: Mon, 23 Apr 2001 01:41:06 +0000
Subject: [PATCH] 1) Decrease the size of needlessly large buffers. For
 example, it    resolved the stack over flow errors reported by Johann
 Zuschlag. 2) Support {oj syntax for 71. servers.

---
 src/interfaces/odbc/columninfo.c | 32 ++++++++++++++++++++++++--------
 src/interfaces/odbc/connection.c | 14 ++++++++------
 src/interfaces/odbc/convert.c    |  1 +
 src/interfaces/odbc/execute.c    |  5 +++++
 src/interfaces/odbc/qresult.c    |  7 ++++---
 5 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/src/interfaces/odbc/columninfo.c b/src/interfaces/odbc/columninfo.c
index 08992241e28..78b6b580ed5 100644
--- a/src/interfaces/odbc/columninfo.c
+++ b/src/interfaces/odbc/columninfo.c
@@ -57,7 +57,8 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
 	Oid			new_adtid;
 	Int2		new_adtsize;
 	Int4		new_atttypmod = -1;
-	char		new_field_name[MAX_MESSAGE_LEN + 1];
+	/* MAX_COLUMN_LEN may be sufficient but for safety */ 
+	char		new_field_name[2 * MAX_COLUMN_LEN + 1];
 	SocketClass *sock;
 	ConnInfo   *ci;
 
@@ -78,7 +79,7 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
 	for (lf = 0; lf < new_num_fields; lf++)
 	{
 
-		SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN);
+		SOCK_get_string(sock, new_field_name, 2 * MAX_COLUMN_LEN);
 		new_adtid = (Oid) SOCK_get_int(sock, 4);
 		new_adtsize = (Int2) SOCK_get_int(sock, 2);
 
@@ -116,16 +117,30 @@ CI_free_memory(ColumnInfoClass *self)
 	for (lf = 0; lf < num_fields; lf++)
 	{
 		if (self->name[lf])
+		{
 			free(self->name[lf]);
+			self->name[lf] = NULL;
+		}
 	}
 
 	/* Safe to call even if null */
-	free(self->name);
-	free(self->adtid);
-	free(self->adtsize);
-	free(self->display_size);
-
-	free(self->atttypmod);
+	self->num_fields = 0;
+	if (self->name)
+		free(self->name);
+	self->name = NULL;
+	if (self->adtid)
+		free(self->adtid);
+	self->adtid = NULL;
+	if (self->adtsize)
+		free(self->adtsize);
+	self->adtsize = NULL;
+	if (self->display_size)
+		free(self->display_size);
+	self->display_size = NULL;
+
+	if (self->atttypmod)
+		free(self->atttypmod);
+	self->atttypmod = NULL;
 }
 
 void
@@ -136,6 +151,7 @@ CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
 	self->num_fields = new_num_fields;
 
 	self->name = (char **) malloc(sizeof(char *) * self->num_fields);
+	memset(self->name, 0,  sizeof(char *) * self->num_fields);
 	self->adtid = (Oid *) malloc(sizeof(Oid) * self->num_fields);
 	self->adtsize = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
 	self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c
index fae3e71b6f9..29e695aca12 100644
--- a/src/interfaces/odbc/connection.c
+++ b/src/interfaces/odbc/connection.c
@@ -913,8 +913,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 	char		swallow;
 	int			id;
 	SocketClass *sock = self->sock;
-	static char msgbuffer[MAX_MESSAGE_LEN + 1];
-	char		cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
+	/* ERROR_MSG_LENGTH is suffcient */
+	static char msgbuffer[ERROR_MSG_LENGTH + 1];
+	char		cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
 												 * this string so dont
 												 * need static */
 
@@ -986,13 +987,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 		{
 			case 'A':			/* Asynchronous Messages are ignored */
 				(void) SOCK_get_int(sock, 4);	/* id of notification */
-				SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
+				SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
 				/* name of the relation the message comes from */
 				break;
 			case 'C':			/* portal query command, no tuples
 								 * returned */
 				/* read in the return message from the backend */
-				SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
+				SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 				if (SOCK_get_errcode(sock) != 0)
 				{
 					self->errornumber = CONNECTION_NO_RESPONSE;
@@ -1146,7 +1147,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 				return res;		/* instead of NULL. Zoltan */
 
 			case 'P':			/* get the Portal name */
-				SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
+				SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
 				break;
 			case 'T':			/* Tuple results start here */
 				result_in = qi ? qi->result_in : NULL;
@@ -1209,7 +1210,8 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
 				c,
 				done;
 	SocketClass *sock = self->sock;
-	static char msgbuffer[MAX_MESSAGE_LEN + 1];
+	/* ERROR_MSG_LENGTH is sufficient */
+	static char msgbuffer[ERROR_MSG_LENGTH + 1];
 	int			i;
 
 	mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
index 8b41fb1c173..2bbc463b32d 100644
--- a/src/interfaces/odbc/convert.c
+++ b/src/interfaces/odbc/convert.c
@@ -1322,6 +1322,7 @@ convert_escape(char *value)
 
 	if ((strcmp(key, "d") == 0) ||
 		(strcmp(key, "t") == 0) ||
+		(strcmp(key, "oj") == 0) || /* {oj syntax support for 7.1 servers */
 		(strcmp(key, "ts") == 0))
 	{
 		/* Literal; return the escape part as-is */
diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c
index 9777f4324c2..5a0fb17b1b4 100644
--- a/src/interfaces/odbc/execute.c
+++ b/src/interfaces/odbc/execute.c
@@ -300,6 +300,11 @@ SQLExecute(
 		stmt->data_at_exec = -1;
 		for (i = 0; i < stmt->parameters_allocated; i++)
 		{
+			Int4 *pcVal = stmt->parameters[i].used;
+			if (pcVal && (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET))
+				stmt->parameters[i].data_at_exec = TRUE;
+			else
+				stmt->parameters[i].data_at_exec = FALSE;
 			/* Check for data at execution parameters */
 			if (stmt->parameters[i].data_at_exec == TRUE)
 			{
diff --git a/src/interfaces/odbc/qresult.c b/src/interfaces/odbc/qresult.c
index c5ec11f9805..8299b960f58 100644
--- a/src/interfaces/odbc/qresult.c
+++ b/src/interfaces/odbc/qresult.c
@@ -368,8 +368,9 @@ QR_next_tuple(QResultClass *self)
 	int			end_tuple = self->rowset_size + self->base;
 	char		corrected = FALSE;
 	TupleField *the_tuples = self->backend_tuples;
-	static char msgbuffer[MAX_MESSAGE_LEN + 1];
-	char		cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
+	/* ERROR_MSG_LENGTH is sufficient */
+	static char msgbuffer[ERROR_MSG_LENGTH + 1];
+	char		cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
 												 * this string so dont
 												 * need static */
 	char		fetch[128];
@@ -528,7 +529,7 @@ QR_next_tuple(QResultClass *self)
 
 
 			case 'C':			/* End of tuple list */
-				SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
+				SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 				QR_set_command(self, cmdbuffer);
 
 				mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
-- 
GitLab