Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6084c07

Browse files
committed
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 ofthese, and apparently Windows still doesn't accept "inf". To avoidsurprising cross-platform behavioral differences, manually check for eachof these spellings if strtod() fails. We were previously handling just"infinity" and "-infinity" that way, but since C99 is most of the worldnow, it seems likely that applications are expecting all these spellingsto work.Per bug #8355 from Basil Peace. It turns out this fix won't actuallyresolve his problem, because Python isn't being this careful; but thatdoesn't mean we shouldn't be.
1 parentc928dc9 commit6084c07

File tree

1 file changed

+81
-25
lines changed

1 file changed

+81
-25
lines changed

‎src/backend/utils/adt/float.c

Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,7 @@ is_infinite(double val)
175175

176176

177177
/*
178-
*float4in- converts "num" to float
179-
* restricted syntax:
180-
* {<sp>} [+|-] {digit} [.{digit}] [<exp>]
181-
* where <sp> is a space, digit is 0-9,
182-
* <exp> is "e" or "E" followed by an integer.
178+
*float4in- converts "num" to float4
183179
*/
184180
Datum
185181
float4in(PG_FUNCTION_ARGS)
@@ -196,6 +192,10 @@ float4in(PG_FUNCTION_ARGS)
196192
*/
197193
orig_num=num;
198194

195+
/* skip leading whitespace */
196+
while (*num!='\0'&&isspace((unsignedchar)*num))
197+
num++;
198+
199199
/*
200200
* Check for an empty-string input to begin with, to avoid the vagaries of
201201
* strtod() on different platforms.
@@ -206,20 +206,23 @@ float4in(PG_FUNCTION_ARGS)
206206
errmsg("invalid input syntax for type real: \"%s\"",
207207
orig_num)));
208208

209-
/* skip leading whitespace */
210-
while (*num!='\0'&&isspace((unsignedchar)*num))
211-
num++;
212-
213209
errno=0;
214210
val=strtod(num,&endptr);
215211

216212
/* did we not see anything that looks like a double? */
217213
if (endptr==num||errno!=0)
218214
{
215+
intsave_errno=errno;
216+
219217
/*
220-
* C99 requires that strtod() accept NaN and [-]Infinity, but not all
221-
* platforms support that yet (and some accept them but set ERANGE
222-
* anyway...) Therefore, we check for these inputs ourselves.
218+
* C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
219+
* but not all platforms support all of these (and some accept them
220+
* but set ERANGE anyway...) Therefore, we check for these inputs
221+
* ourselves if strtod() fails.
222+
*
223+
* Note: C99 also requires hexadecimal input as well as some extended
224+
* forms of NaN, but we consider these forms unportable and don't try
225+
* to support them. You can use 'em if your strtod() takes 'em.
223226
*/
224227
if (pg_strncasecmp(num,"NaN",3)==0)
225228
{
@@ -231,12 +234,32 @@ float4in(PG_FUNCTION_ARGS)
231234
val=get_float4_infinity();
232235
endptr=num+8;
233236
}
237+
elseif (pg_strncasecmp(num,"+Infinity",9)==0)
238+
{
239+
val=get_float4_infinity();
240+
endptr=num+9;
241+
}
234242
elseif (pg_strncasecmp(num,"-Infinity",9)==0)
235243
{
236244
val=-get_float4_infinity();
237245
endptr=num+9;
238246
}
239-
elseif (errno==ERANGE)
247+
elseif (pg_strncasecmp(num,"inf",3)==0)
248+
{
249+
val=get_float4_infinity();
250+
endptr=num+3;
251+
}
252+
elseif (pg_strncasecmp(num,"+inf",4)==0)
253+
{
254+
val=get_float4_infinity();
255+
endptr=num+4;
256+
}
257+
elseif (pg_strncasecmp(num,"-inf",4)==0)
258+
{
259+
val=-get_float4_infinity();
260+
endptr=num+4;
261+
}
262+
elseif (save_errno==ERANGE)
240263
ereport(ERROR,
241264
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
242265
errmsg("\"%s\" is out of range for type real",
@@ -274,6 +297,11 @@ float4in(PG_FUNCTION_ARGS)
274297
val=get_float4_infinity();
275298
endptr=num+8;
276299
}
300+
elseif (pg_strncasecmp(num,"+Infinity",9)==0)
301+
{
302+
val=get_float4_infinity();
303+
endptr=num+9;
304+
}
277305
elseif (pg_strncasecmp(num,"-Infinity",9)==0)
278306
{
279307
val=-get_float4_infinity();
@@ -369,10 +397,6 @@ float4send(PG_FUNCTION_ARGS)
369397

370398
/*
371399
*float8in- converts "num" to float8
372-
* restricted syntax:
373-
* {<sp>} [+|-] {digit} [.{digit}] [<exp>]
374-
* where <sp> is a space, digit is 0-9,
375-
* <exp> is "e" or "E" followed by an integer.
376400
*/
377401
Datum
378402
float8in(PG_FUNCTION_ARGS)
@@ -389,6 +413,10 @@ float8in(PG_FUNCTION_ARGS)
389413
*/
390414
orig_num=num;
391415

416+
/* skip leading whitespace */
417+
while (*num!='\0'&&isspace((unsignedchar)*num))
418+
num++;
419+
392420
/*
393421
* Check for an empty-string input to begin with, to avoid the vagaries of
394422
* strtod() on different platforms.
@@ -399,20 +427,23 @@ float8in(PG_FUNCTION_ARGS)
399427
errmsg("invalid input syntax for type double precision: \"%s\"",
400428
orig_num)));
401429

402-
/* skip leading whitespace */
403-
while (*num!='\0'&&isspace((unsignedchar)*num))
404-
num++;
405-
406430
errno=0;
407431
val=strtod(num,&endptr);
408432

409433
/* did we not see anything that looks like a double? */
410434
if (endptr==num||errno!=0)
411435
{
436+
intsave_errno=errno;
437+
412438
/*
413-
* C99 requires that strtod() accept NaN and [-]Infinity, but not all
414-
* platforms support that yet (and some accept them but set ERANGE
415-
* anyway...) Therefore, we check for these inputs ourselves.
439+
* C99 requires that strtod() accept NaN, [+-]Infinity, and [+-]Inf,
440+
* but not all platforms support all of these (and some accept them
441+
* but set ERANGE anyway...) Therefore, we check for these inputs
442+
* ourselves if strtod() fails.
443+
*
444+
* Note: C99 also requires hexadecimal input as well as some extended
445+
* forms of NaN, but we consider these forms unportable and don't try
446+
* to support them. You can use 'em if your strtod() takes 'em.
416447
*/
417448
if (pg_strncasecmp(num,"NaN",3)==0)
418449
{
@@ -424,12 +455,32 @@ float8in(PG_FUNCTION_ARGS)
424455
val=get_float8_infinity();
425456
endptr=num+8;
426457
}
458+
elseif (pg_strncasecmp(num,"+Infinity",9)==0)
459+
{
460+
val=get_float8_infinity();
461+
endptr=num+9;
462+
}
427463
elseif (pg_strncasecmp(num,"-Infinity",9)==0)
428464
{
429465
val=-get_float8_infinity();
430466
endptr=num+9;
431467
}
432-
elseif (errno==ERANGE)
468+
elseif (pg_strncasecmp(num,"inf",3)==0)
469+
{
470+
val=get_float8_infinity();
471+
endptr=num+3;
472+
}
473+
elseif (pg_strncasecmp(num,"+inf",4)==0)
474+
{
475+
val=get_float8_infinity();
476+
endptr=num+4;
477+
}
478+
elseif (pg_strncasecmp(num,"-inf",4)==0)
479+
{
480+
val=-get_float8_infinity();
481+
endptr=num+4;
482+
}
483+
elseif (save_errno==ERANGE)
433484
ereport(ERROR,
434485
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
435486
errmsg("\"%s\" is out of range for type double precision",
@@ -467,6 +518,11 @@ float8in(PG_FUNCTION_ARGS)
467518
val=get_float8_infinity();
468519
endptr=num+8;
469520
}
521+
elseif (pg_strncasecmp(num,"+Infinity",9)==0)
522+
{
523+
val=get_float8_infinity();
524+
endptr=num+9;
525+
}
470526
elseif (pg_strncasecmp(num,"-Infinity",9)==0)
471527
{
472528
val=-get_float8_infinity();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp