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

Commiteb8312a

Browse files
committed
Detect bad input for types xid, xid8, and cid.
Historically these input functions just called strtoul or strtoulland returned the result, with no error detection whatever. Upgradethem to reject garbage input and out-of-range values, similarly toour other numeric input routines.To share the code for this with type oid, adjust the existing"oidin_subr" to be agnostic about the SQL name of the type it ishandling, and move it to numutils.c; then clone it for 64-bit types.Because the xid types previously accepted hex and octal input byreason of calling strtoul[l] with third argument zero, I made thecommon subroutine do that too, with the consequence that type oidnow also accepts hex and octal input. In view of6fcda9a, thatseems like a good thing.While at it, simplify the existing over-complicated handling ofsyntax errors from strtoul: we only need one ereturn not three.Discussion:https://postgr.es/m/3526121.1672000729@sss.pgh.pa.us
1 parent63c844a commiteb8312a

File tree

6 files changed

+222
-116
lines changed

6 files changed

+222
-116
lines changed

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

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,156 @@ pg_strtoint64_safe(const char *s, Node *escontext)
477477
"bigint",s)));
478478
}
479479

480+
/*
481+
* Convert input string to an unsigned 32 bit integer.
482+
*
483+
* Allows any number of leading or trailing whitespace characters.
484+
*
485+
* If endloc isn't NULL, store a pointer to the rest of the string there,
486+
* so that caller can parse the rest. Otherwise, it's an error if anything
487+
* but whitespace follows.
488+
*
489+
* typname is what is reported in error messges.
490+
*
491+
* If escontext points to an ErrorSaveContext node, that is filled instead
492+
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
493+
* to detect errors.
494+
*/
495+
uint32
496+
uint32in_subr(constchar*s,char**endloc,
497+
constchar*typname,Node*escontext)
498+
{
499+
uint32result;
500+
unsigned longcvt;
501+
char*endptr;
502+
503+
errno=0;
504+
cvt=strtoul(s,&endptr,0);
505+
506+
/*
507+
* strtoul() normally only sets ERANGE. On some systems it may also set
508+
* EINVAL, which simply means it couldn't parse the input string. Be sure
509+
* to report that the same way as the standard error indication (that
510+
* endptr == s).
511+
*/
512+
if ((errno&&errno!=ERANGE)||endptr==s)
513+
ereturn(escontext,0,
514+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
515+
errmsg("invalid input syntax for type %s: \"%s\"",
516+
typname,s)));
517+
518+
if (errno==ERANGE)
519+
ereturn(escontext,0,
520+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
521+
errmsg("value \"%s\" is out of range for type %s",
522+
s,typname)));
523+
524+
if (endloc)
525+
{
526+
/* caller wants to deal with rest of string */
527+
*endloc=endptr;
528+
}
529+
else
530+
{
531+
/* allow only whitespace after number */
532+
while (*endptr&&isspace((unsignedchar)*endptr))
533+
endptr++;
534+
if (*endptr)
535+
ereturn(escontext,0,
536+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
537+
errmsg("invalid input syntax for type %s: \"%s\"",
538+
typname,s)));
539+
}
540+
541+
result= (uint32)cvt;
542+
543+
/*
544+
* Cope with possibility that unsigned long is wider than uint32, in which
545+
* case strtoul will not raise an error for some values that are out of
546+
* the range of uint32.
547+
*
548+
* For backwards compatibility, we want to accept inputs that are given
549+
* with a minus sign, so allow the input value if it matches after either
550+
* signed or unsigned extension to long.
551+
*
552+
* To ensure consistent results on 32-bit and 64-bit platforms, make sure
553+
* the error message is the same as if strtoul() had returned ERANGE.
554+
*/
555+
#ifPG_UINT32_MAX!=ULONG_MAX
556+
if (cvt!= (unsigned long)result&&
557+
cvt!= (unsigned long) ((int)result))
558+
ereturn(escontext,0,
559+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
560+
errmsg("value \"%s\" is out of range for type %s",
561+
s,typname)));
562+
#endif
563+
564+
returnresult;
565+
}
566+
567+
/*
568+
* Convert input string to an unsigned 64 bit integer.
569+
*
570+
* Allows any number of leading or trailing whitespace characters.
571+
*
572+
* If endloc isn't NULL, store a pointer to the rest of the string there,
573+
* so that caller can parse the rest. Otherwise, it's an error if anything
574+
* but whitespace follows.
575+
*
576+
* typname is what is reported in error messges.
577+
*
578+
* If escontext points to an ErrorSaveContext node, that is filled instead
579+
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
580+
* to detect errors.
581+
*/
582+
uint64
583+
uint64in_subr(constchar*s,char**endloc,
584+
constchar*typname,Node*escontext)
585+
{
586+
uint64result;
587+
char*endptr;
588+
589+
errno=0;
590+
result=strtou64(s,&endptr,0);
591+
592+
/*
593+
* strtoul[l] normally only sets ERANGE. On some systems it may also set
594+
* EINVAL, which simply means it couldn't parse the input string. Be sure
595+
* to report that the same way as the standard error indication (that
596+
* endptr == s).
597+
*/
598+
if ((errno&&errno!=ERANGE)||endptr==s)
599+
ereturn(escontext,0,
600+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
601+
errmsg("invalid input syntax for type %s: \"%s\"",
602+
typname,s)));
603+
604+
if (errno==ERANGE)
605+
ereturn(escontext,0,
606+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
607+
errmsg("value \"%s\" is out of range for type %s",
608+
s,typname)));
609+
610+
if (endloc)
611+
{
612+
/* caller wants to deal with rest of string */
613+
*endloc=endptr;
614+
}
615+
else
616+
{
617+
/* allow only whitespace after number */
618+
while (*endptr&&isspace((unsignedchar)*endptr))
619+
endptr++;
620+
if (*endptr)
621+
ereturn(escontext,0,
622+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
623+
errmsg("invalid input syntax for type %s: \"%s\"",
624+
typname,s)));
625+
}
626+
627+
returnresult;
628+
}
629+
480630
/*
481631
* pg_itoa: converts a signed 16-bit integer to its string representation
482632
* and returns strlen(a).

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

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -32,106 +32,13 @@
3232
* USER I/O ROUTINES *
3333
*****************************************************************************/
3434

35-
/*
36-
* Parse a single OID and return its value.
37-
*
38-
* If endloc isn't NULL, store a pointer to the rest of the string there,
39-
* so that caller can parse the rest. Otherwise, it's an error if anything
40-
* but whitespace follows.
41-
*
42-
* If escontext points to an ErrorSaveContext node, that is filled instead
43-
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
44-
* to detect errors.
45-
*/
46-
staticOid
47-
oidin_subr(constchar*s,char**endloc,Node*escontext)
48-
{
49-
unsigned longcvt;
50-
char*endptr;
51-
Oidresult;
52-
53-
if (*s=='\0')
54-
ereturn(escontext,InvalidOid,
55-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
56-
errmsg("invalid input syntax for type %s: \"%s\"",
57-
"oid",s)));
58-
59-
errno=0;
60-
cvt=strtoul(s,&endptr,10);
61-
62-
/*
63-
* strtoul() normally only sets ERANGE. On some systems it also may set
64-
* EINVAL, which simply means it couldn't parse the input string. This is
65-
* handled by the second "if" consistent across platforms.
66-
*/
67-
if (errno&&errno!=ERANGE&&errno!=EINVAL)
68-
ereturn(escontext,InvalidOid,
69-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
70-
errmsg("invalid input syntax for type %s: \"%s\"",
71-
"oid",s)));
72-
73-
if (endptr==s&&*s!='\0')
74-
ereturn(escontext,InvalidOid,
75-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
76-
errmsg("invalid input syntax for type %s: \"%s\"",
77-
"oid",s)));
78-
79-
if (errno==ERANGE)
80-
ereturn(escontext,InvalidOid,
81-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
82-
errmsg("value \"%s\" is out of range for type %s",
83-
s,"oid")));
84-
85-
if (endloc)
86-
{
87-
/* caller wants to deal with rest of string */
88-
*endloc=endptr;
89-
}
90-
else
91-
{
92-
/* allow only whitespace after number */
93-
while (*endptr&&isspace((unsignedchar)*endptr))
94-
endptr++;
95-
if (*endptr)
96-
ereturn(escontext,InvalidOid,
97-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
98-
errmsg("invalid input syntax for type %s: \"%s\"",
99-
"oid",s)));
100-
}
101-
102-
result= (Oid)cvt;
103-
104-
/*
105-
* Cope with possibility that unsigned long is wider than Oid, in which
106-
* case strtoul will not raise an error for some values that are out of
107-
* the range of Oid.
108-
*
109-
* For backwards compatibility, we want to accept inputs that are given
110-
* with a minus sign, so allow the input value if it matches after either
111-
* signed or unsigned extension to long.
112-
*
113-
* To ensure consistent results on 32-bit and 64-bit platforms, make sure
114-
* the error message is the same as if strtoul() had returned ERANGE.
115-
*/
116-
#ifOID_MAX!=ULONG_MAX
117-
if (cvt!= (unsigned long)result&&
118-
cvt!= (unsigned long) ((int)result))
119-
ereturn(escontext,InvalidOid,
120-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
121-
errmsg("value \"%s\" is out of range for type %s",
122-
s,"oid")));
123-
#endif
124-
125-
returnresult;
126-
}
127-
12835
Datum
12936
oidin(PG_FUNCTION_ARGS)
13037
{
13138
char*s=PG_GETARG_CSTRING(0);
13239
Oidresult;
13340

134-
result=oidin_subr(s,NULL,fcinfo->context);
41+
result=uint32in_subr(s,NULL,"oid",fcinfo->context);
13542
PG_RETURN_OID(result);
13643
}
13744

@@ -218,7 +125,8 @@ oidvectorin(PG_FUNCTION_ARGS)
218125
oidString++;
219126
if (*oidString=='\0')
220127
break;
221-
result->values[n]=oidin_subr(oidString,&oidString,escontext);
128+
result->values[n]=uint32in_subr(oidString,&oidString,
129+
"oid",escontext);
222130
if (SOFT_ERROR_OCCURRED(escontext))
223131
PG_RETURN_NULL();
224132
}
@@ -339,7 +247,8 @@ oidparse(Node *node)
339247
* constants by the lexer. Accept these if they are valid OID
340248
* strings.
341249
*/
342-
returnoidin_subr(castNode(Float,node)->fval,NULL,NULL);
250+
returnuint32in_subr(castNode(Float,node)->fval,NULL,
251+
"oid",NULL);
343252
default:
344253
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(node));
345254
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ Datum
3131
xidin(PG_FUNCTION_ARGS)
3232
{
3333
char*str=PG_GETARG_CSTRING(0);
34+
TransactionIdresult;
3435

35-
PG_RETURN_TRANSACTIONID((TransactionId)strtoul(str,NULL,0));
36+
result=uint32in_subr(str,NULL,"xid",fcinfo->context);
37+
PG_RETURN_TRANSACTIONID(result);
3638
}
3739

3840
Datum
@@ -183,8 +185,10 @@ Datum
183185
xid8in(PG_FUNCTION_ARGS)
184186
{
185187
char*str=PG_GETARG_CSTRING(0);
188+
uint64result;
186189

187-
PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(strtou64(str,NULL,0)));
190+
result=uint64in_subr(str,NULL,"xid8",fcinfo->context);
191+
PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(result));
188192
}
189193

190194
Datum
@@ -321,8 +325,10 @@ Datum
321325
cidin(PG_FUNCTION_ARGS)
322326
{
323327
char*str=PG_GETARG_CSTRING(0);
328+
CommandIdresult;
324329

325-
PG_RETURN_COMMANDID((CommandId)strtoul(str,NULL,0));
330+
result=uint32in_subr(str,NULL,"cid",fcinfo->context);
331+
PG_RETURN_COMMANDID(result);
326332
}
327333

328334
/*

‎src/include/utils/builtins.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ extern int32 pg_strtoint32(const char *s);
5151
externint32pg_strtoint32_safe(constchar*s,Node*escontext);
5252
externint64pg_strtoint64(constchar*s);
5353
externint64pg_strtoint64_safe(constchar*s,Node*escontext);
54+
externuint32uint32in_subr(constchar*s,char**endloc,
55+
constchar*typname,Node*escontext);
56+
externuint64uint64in_subr(constchar*s,char**endloc,
57+
constchar*typname,Node*escontext);
5458
externintpg_itoa(int16i,char*a);
5559
externintpg_ultoa_n(uint32value,char*a);
5660
externintpg_ulltoa_n(uint64value,char*a);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp