Float value 'Infinity' is cast to numeric 1 on Windows

Started by Taiki Kondoover 8 years ago3 messages
#1Taiki Kondo
tai-kondo@yk.jp.nec.com
1 attachment(s)

Hi all,

I build PostgreSQL 9.6.5 by Visual Studio 2013 on Windows, I found weird behavior on it.

I execute following SQL, occurring ERROR is expected, but I got mysterious value 1.

postgres=# select (float8 'inf')::numeric;
numeric
---------
1
(1 row)

On Windows, at least Visual Studio, the string of float/double value meaning
infinity is "1.#INF" not "inf". So, set_var_from_str() called from float8_numeric()
in utils/adt/numeric.c will return numeric value 1, and no one checks this situation.

This situation is also occurring by cast from float4.

I wrote a patch to add check this situation.
Please find attached.

Sincerely,

--
Taiki Kondo
NEC Solution Innovators, Ltd.

Attachments:

fix_infinity_to_1.patchapplication/octet-stream; name=fix_infinity_to_1.patchDownload
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index ddc44d5179..e871b94bb8 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -3139,6 +3139,7 @@ float8_numeric(PG_FUNCTION_ARGS)
 	Numeric		res;
 	NumericVar	result;
 	char		buf[DBL_DIG + 100];
+	char		*cp;
 
 	if (isnan(val))
 		PG_RETURN_NUMERIC(make_result(&const_nan));
@@ -3148,7 +3149,14 @@ float8_numeric(PG_FUNCTION_ARGS)
 	init_var(&result);
 
 	/* Assume we need not worry about leading/trailing spaces */
-	(void) set_var_from_str(buf, buf, &result);
+	cp = set_var_from_str(buf, buf, &result);
+
+	/* We have to check if val is invalid actually. */
+	if (*cp)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"numeric", buf)));
 
 	res = make_result(&result);
 
@@ -3205,6 +3213,7 @@ float4_numeric(PG_FUNCTION_ARGS)
 	Numeric		res;
 	NumericVar	result;
 	char		buf[FLT_DIG + 100];
+	char		*cp;
 
 	if (isnan(val))
 		PG_RETURN_NUMERIC(make_result(&const_nan));
@@ -3214,7 +3223,14 @@ float4_numeric(PG_FUNCTION_ARGS)
 	init_var(&result);
 
 	/* Assume we need not worry about leading/trailing spaces */
-	(void) set_var_from_str(buf, buf, &result);
+	cp = set_var_from_str(buf, buf, &result);
+
+	/* We have to check if val is invalid actually. */
+	if (*cp)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid input syntax for type %s: \"%s\"",
+						"numeric", buf)));
 
 	res = make_result(&result);
 
#2Kohei KaiGai
kaigai@heterodb.com
In reply to: Taiki Kondo (#1)
Re: Float value 'Infinity' is cast to numeric 1 on Windows

Hello,

Does it make sense to put a check of "isinf(val)" and ereport prior to
the snprintf()?
It is a lightweight check more than set_var_from_str().

Thanks,

2017-09-27 19:41 GMT+09:00 Taiki Kondo <tai-kondo@yk.jp.nec.com>:

Hi all,

I build PostgreSQL 9.6.5 by Visual Studio 2013 on Windows, I found weird behavior on it.

I execute following SQL, occurring ERROR is expected, but I got mysterious value 1.

postgres=# select (float8 'inf')::numeric;
numeric
---------
1
(1 row)

On Windows, at least Visual Studio, the string of float/double value meaning
infinity is "1.#INF" not "inf". So, set_var_from_str() called from float8_numeric()
in utils/adt/numeric.c will return numeric value 1, and no one checks this situation.

This situation is also occurring by cast from float4.

I wrote a patch to add check this situation.
Please find attached.

Sincerely,

--
Taiki Kondo
NEC Solution Innovators, Ltd.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
HeteroDB, Inc / The PG-Strom Project
KaiGai Kohei <kaigai@heterodb.com>

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Kohei KaiGai (#2)
Re: [HACKERS] Float value 'Infinity' is cast to numeric 1 on Windows

Kohei KaiGai <kaigai@heterodb.com> writes:

Does it make sense to put a check of "isinf(val)" and ereport prior to
the snprintf()?

Yeah, that was my reaction too. Obviously this wasn't thought about
in the original coding ...

regards, tom lane

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs