From e2940f9fc9245f479258ad345356f13ec4aedbb0 Mon Sep 17 00:00:00 2001
From: Gao Zengqi <pgf00a@gmail.com>
Date: Thu, 26 Oct 2017 07:34:31 +0000
Subject: [PATCH 2/2] Fix endless loop in ecpg with informix mode

---
 src/interfaces/ecpg/ecpglib/data.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index a2f3916..ab447d8 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -44,7 +44,7 @@ array_boundary(enum ARRAY_TYPE isarray, char c)
 
 /* returns true if some garbage is found at the end of the scanned string */
 static bool
-garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
+garbage_left(enum ARRAY_TYPE isarray, char **scan_length, enum COMPAT_MODE compat)
 {
 	/*
 	 * INFORMIX allows for selecting a numeric into an int, the result is
@@ -52,13 +52,19 @@ garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat
 	 */
 	if (isarray == ECPG_ARRAY_NONE)
 	{
-		if (INFORMIX_MODE(compat) && *scan_length == '.')
+		if (INFORMIX_MODE(compat) && **scan_length == '.')
+		{
+			/* skip invalid characters */
+			do {
+				(*scan_length)++;
+			} while (**scan_length != ' ' && **scan_length != '\0');
 			return false;
+		}
 
-		if (*scan_length != ' ' && *scan_length != '\0')
+		if (**scan_length != ' ' && **scan_length != '\0')
 			return true;
 	}
-	else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, *scan_length) && !array_boundary(isarray, *scan_length))
+	else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
 		return true;
 
 	return false;
@@ -303,7 +309,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 				case ECPGt_int:
 				case ECPGt_long:
 					res = strtol(pval, &scan_length, 10);
-					if (garbage_left(isarray, scan_length, compat))
+					if (garbage_left(isarray, &scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_INT_FORMAT,
 								   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -332,7 +338,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 				case ECPGt_unsigned_int:
 				case ECPGt_unsigned_long:
 					ures = strtoul(pval, &scan_length, 10);
-					if (garbage_left(isarray, scan_length, compat))
+					if (garbage_left(isarray, &scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_UINT_FORMAT,
 								   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -361,7 +367,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 #ifdef HAVE_STRTOLL
 				case ECPGt_long_long:
 					*((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
-					if (garbage_left(isarray, scan_length, compat))
+					if (garbage_left(isarray, &scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
 						return false;
@@ -373,7 +379,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 #ifdef HAVE_STRTOULL
 				case ECPGt_unsigned_long_long:
 					*((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
-					if (garbage_left(isarray, scan_length, compat))
+					if (garbage_left(isarray, &scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
 						return false;
@@ -395,7 +401,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					if (isarray && *scan_length == '"')
 						scan_length++;
 
-					if (garbage_left(isarray, scan_length, compat))
+					if (garbage_left(isarray, &scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
 								   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -593,7 +599,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					}
 					else
 					{
-						if (!isarray && garbage_left(isarray, scan_length, compat))
+						if (!isarray && garbage_left(isarray, &scan_length, compat))
 						{
 							free(nres);
 							ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
@@ -651,7 +657,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 						if (*scan_length == '"')
 							scan_length++;
 
-						if (!isarray && garbage_left(isarray, scan_length, compat))
+						if (!isarray && garbage_left(isarray, &scan_length, compat))
 						{
 							free(ires);
 							ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
@@ -701,7 +707,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 						if (*scan_length == '"')
 							scan_length++;
 
-						if (!isarray && garbage_left(isarray, scan_length, compat))
+						if (!isarray && garbage_left(isarray, &scan_length, compat))
 						{
 							ecpg_raise(lineno, ECPG_DATE_FORMAT,
 									   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -749,7 +755,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 						if (*scan_length == '"')
 							scan_length++;
 
-						if (!isarray && garbage_left(isarray, scan_length, compat))
+						if (!isarray && garbage_left(isarray, &scan_length, compat))
 						{
 							ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
 									   ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
-- 
2.7.4

