mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Make sure float4in/float8in accept all standard spellings of "infinity".
The C99 and POSIX standards require strtod() to accept all these spellings (case-insensitively): "inf", "+inf", "-inf", "infinity", "+infinity", "-infinity". However, pre-C99 systems might accept only some or none of these, and apparently Windows still doesn't accept "inf". To avoid surprising cross-platform behavioral differences, manually check for each of these spellings if strtod() fails. We were previously handling just "infinity" and "-infinity" that way, but since C99 is most of the world now, it seems likely that applications are expecting all these spellings to work. Per bug #8355 from Basil Peace. It turns out this fix won't actually resolve his problem, because Python isn't being this careful; but that doesn't mean we shouldn't be.
This commit is contained in:
		@@ -176,11 +176,7 @@ is_infinite(double val)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *		float4in		- converts "num" to float
 | 
					 *		float4in		- converts "num" to float4
 | 
				
			||||||
 *						  restricted syntax:
 | 
					 | 
				
			||||||
 *						  {<sp>} [+|-] {digit} [.{digit}] [<exp>]
 | 
					 | 
				
			||||||
 *						  where <sp> is a space, digit is 0-9,
 | 
					 | 
				
			||||||
 *						  <exp> is "e" or "E" followed by an integer.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Datum
 | 
					Datum
 | 
				
			||||||
float4in(PG_FUNCTION_ARGS)
 | 
					float4in(PG_FUNCTION_ARGS)
 | 
				
			||||||
@@ -197,6 +193,10 @@ float4in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	orig_num = num;
 | 
						orig_num = num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* skip leading whitespace */
 | 
				
			||||||
 | 
						while (*num != '\0' && isspace((unsigned char) *num))
 | 
				
			||||||
 | 
							num++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Check for an empty-string input to begin with, to avoid the vagaries of
 | 
						 * Check for an empty-string input to begin with, to avoid the vagaries of
 | 
				
			||||||
	 * strtod() on different platforms.
 | 
						 * strtod() on different platforms.
 | 
				
			||||||
@@ -207,10 +207,6 @@ float4in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
				 errmsg("invalid input syntax for type real: \"%s\"",
 | 
									 errmsg("invalid input syntax for type real: \"%s\"",
 | 
				
			||||||
						orig_num)));
 | 
											orig_num)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* skip leading whitespace */
 | 
					 | 
				
			||||||
	while (*num != '\0' && isspace((unsigned char) *num))
 | 
					 | 
				
			||||||
		num++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	errno = 0;
 | 
						errno = 0;
 | 
				
			||||||
	val = strtod(num, &endptr);
 | 
						val = strtod(num, &endptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -220,9 +216,14 @@ float4in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
		int			save_errno = errno;
 | 
							int			save_errno = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * C99 requires that strtod() accept NaN and [-]Infinity, but not all
 | 
							 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
 | 
				
			||||||
		 * platforms support that yet (and some accept them but set ERANGE
 | 
							 * but not all platforms support all of these (and some accept them
 | 
				
			||||||
		 * anyway...)  Therefore, we check for these inputs ourselves.
 | 
							 * but set ERANGE anyway...)  Therefore, we check for these inputs
 | 
				
			||||||
 | 
							 * ourselves if strtod() fails.
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * Note: C99 also requires hexadecimal input as well as some extended
 | 
				
			||||||
 | 
							 * forms of NaN, but we consider these forms unportable and don't try
 | 
				
			||||||
 | 
							 * to support them.  You can use 'em if your strtod() takes 'em.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (pg_strncasecmp(num, "NaN", 3) == 0)
 | 
							if (pg_strncasecmp(num, "NaN", 3) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -234,11 +235,31 @@ float4in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
			val = get_float4_infinity();
 | 
								val = get_float4_infinity();
 | 
				
			||||||
			endptr = num + 8;
 | 
								endptr = num + 8;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float4_infinity();
 | 
				
			||||||
 | 
								endptr = num + 9;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
							else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			val = -get_float4_infinity();
 | 
								val = -get_float4_infinity();
 | 
				
			||||||
			endptr = num + 9;
 | 
								endptr = num + 9;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "inf", 3) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float4_infinity();
 | 
				
			||||||
 | 
								endptr = num + 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+inf", 4) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float4_infinity();
 | 
				
			||||||
 | 
								endptr = num + 4;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "-inf", 4) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = -get_float4_infinity();
 | 
				
			||||||
 | 
								endptr = num + 4;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (save_errno == ERANGE)
 | 
							else if (save_errno == ERANGE)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -287,6 +308,11 @@ float4in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
			val = get_float4_infinity();
 | 
								val = get_float4_infinity();
 | 
				
			||||||
			endptr = num + 8;
 | 
								endptr = num + 8;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float4_infinity();
 | 
				
			||||||
 | 
								endptr = num + 9;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
							else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			val = -get_float4_infinity();
 | 
								val = -get_float4_infinity();
 | 
				
			||||||
@@ -382,10 +408,6 @@ float4send(PG_FUNCTION_ARGS)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *		float8in		- converts "num" to float8
 | 
					 *		float8in		- converts "num" to float8
 | 
				
			||||||
 *						  restricted syntax:
 | 
					 | 
				
			||||||
 *						  {<sp>} [+|-] {digit} [.{digit}] [<exp>]
 | 
					 | 
				
			||||||
 *						  where <sp> is a space, digit is 0-9,
 | 
					 | 
				
			||||||
 *						  <exp> is "e" or "E" followed by an integer.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Datum
 | 
					Datum
 | 
				
			||||||
float8in(PG_FUNCTION_ARGS)
 | 
					float8in(PG_FUNCTION_ARGS)
 | 
				
			||||||
@@ -402,6 +424,10 @@ float8in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	orig_num = num;
 | 
						orig_num = num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* skip leading whitespace */
 | 
				
			||||||
 | 
						while (*num != '\0' && isspace((unsigned char) *num))
 | 
				
			||||||
 | 
							num++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Check for an empty-string input to begin with, to avoid the vagaries of
 | 
						 * Check for an empty-string input to begin with, to avoid the vagaries of
 | 
				
			||||||
	 * strtod() on different platforms.
 | 
						 * strtod() on different platforms.
 | 
				
			||||||
@@ -412,10 +438,6 @@ float8in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
			 errmsg("invalid input syntax for type double precision: \"%s\"",
 | 
								 errmsg("invalid input syntax for type double precision: \"%s\"",
 | 
				
			||||||
					orig_num)));
 | 
										orig_num)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* skip leading whitespace */
 | 
					 | 
				
			||||||
	while (*num != '\0' && isspace((unsigned char) *num))
 | 
					 | 
				
			||||||
		num++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	errno = 0;
 | 
						errno = 0;
 | 
				
			||||||
	val = strtod(num, &endptr);
 | 
						val = strtod(num, &endptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -425,9 +447,14 @@ float8in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
		int			save_errno = errno;
 | 
							int			save_errno = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * C99 requires that strtod() accept NaN and [-]Infinity, but not all
 | 
							 * C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
 | 
				
			||||||
		 * platforms support that yet (and some accept them but set ERANGE
 | 
							 * but not all platforms support all of these (and some accept them
 | 
				
			||||||
		 * anyway...)  Therefore, we check for these inputs ourselves.
 | 
							 * but set ERANGE anyway...)  Therefore, we check for these inputs
 | 
				
			||||||
 | 
							 * ourselves if strtod() fails.
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * Note: C99 also requires hexadecimal input as well as some extended
 | 
				
			||||||
 | 
							 * forms of NaN, but we consider these forms unportable and don't try
 | 
				
			||||||
 | 
							 * to support them.  You can use 'em if your strtod() takes 'em.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (pg_strncasecmp(num, "NaN", 3) == 0)
 | 
							if (pg_strncasecmp(num, "NaN", 3) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -439,11 +466,31 @@ float8in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
			val = get_float8_infinity();
 | 
								val = get_float8_infinity();
 | 
				
			||||||
			endptr = num + 8;
 | 
								endptr = num + 8;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float8_infinity();
 | 
				
			||||||
 | 
								endptr = num + 9;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
							else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			val = -get_float8_infinity();
 | 
								val = -get_float8_infinity();
 | 
				
			||||||
			endptr = num + 9;
 | 
								endptr = num + 9;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "inf", 3) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float8_infinity();
 | 
				
			||||||
 | 
								endptr = num + 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+inf", 4) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float8_infinity();
 | 
				
			||||||
 | 
								endptr = num + 4;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "-inf", 4) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = -get_float8_infinity();
 | 
				
			||||||
 | 
								endptr = num + 4;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (save_errno == ERANGE)
 | 
							else if (save_errno == ERANGE)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -492,6 +539,11 @@ float8in(PG_FUNCTION_ARGS)
 | 
				
			|||||||
			val = get_float8_infinity();
 | 
								val = get_float8_infinity();
 | 
				
			||||||
			endptr = num + 8;
 | 
								endptr = num + 8;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								val = get_float8_infinity();
 | 
				
			||||||
 | 
								endptr = num + 9;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
							else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			val = -get_float8_infinity();
 | 
								val = -get_float8_infinity();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user