pg_strtoint32_base_10_first.patch
text/plain
Filename: pg_strtoint32_base_10_first.patch
Type: text/plain
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/adt/numutils.c | 35 | 29 |
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index 471fbb7ee6..60c90f7252 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -314,113 +314,119 @@ pg_strtoint32_safe(const char *s, Node *escontext)
else if (*ptr == '+')
ptr++;
- /* process digits */
- if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
+ /* process decimal digits */
+ if (isdigit((unsigned char) ptr[0]) &&
+ (isdigit((unsigned char) ptr[1]) || ptr[1] == '_' || ptr[1] == '\0' || isspace(ptr[1])))
{
- firstdigit = ptr += 2;
+ firstdigit = ptr;
while (*ptr)
{
- if (isxdigit((unsigned char) *ptr))
+ if (isdigit((unsigned char) *ptr))
{
- if (unlikely(tmp > -(PG_INT32_MIN / 16)))
+ if (unlikely(tmp > -(PG_INT32_MIN / 10)))
goto out_of_range;
- tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
+ tmp = tmp * 10 + (*ptr++ - '0');
}
else if (*ptr == '_')
{
- /* underscore must be followed by more digits */
+ /* underscore may not be first */
+ if (unlikely(ptr == firstdigit))
+ goto invalid_syntax;
+ /* and it must be followed by more digits */
ptr++;
- if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
+ if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
goto invalid_syntax;
}
else
break;
}
}
- else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
+ /* process hex digits */
+ else if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
{
firstdigit = ptr += 2;
while (*ptr)
{
- if (*ptr >= '0' && *ptr <= '7')
+ if (isxdigit((unsigned char) *ptr))
{
- if (unlikely(tmp > -(PG_INT32_MIN / 8)))
+ if (unlikely(tmp > -(PG_INT32_MIN / 16)))
goto out_of_range;
- tmp = tmp * 8 + (*ptr++ - '0');
+ tmp = tmp * 16 + hexlookup[(unsigned char) *ptr++];
}
else if (*ptr == '_')
{
/* underscore must be followed by more digits */
ptr++;
- if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
+ if (*ptr == '\0' || !isxdigit((unsigned char) *ptr))
goto invalid_syntax;
}
else
break;
}
}
- else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
+ /* process octal digits */
+ else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
{
firstdigit = ptr += 2;
while (*ptr)
{
- if (*ptr >= '0' && *ptr <= '1')
+ if (*ptr >= '0' && *ptr <= '7')
{
- if (unlikely(tmp > -(PG_INT32_MIN / 2)))
+ if (unlikely(tmp > -(PG_INT32_MIN / 8)))
goto out_of_range;
- tmp = tmp * 2 + (*ptr++ - '0');
+ tmp = tmp * 8 + (*ptr++ - '0');
}
else if (*ptr == '_')
{
/* underscore must be followed by more digits */
ptr++;
- if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
+ if (*ptr == '\0' || *ptr < '0' || *ptr > '7')
goto invalid_syntax;
}
else
break;
}
}
- else
+ /* process binary digits */
+ else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
{
- firstdigit = ptr;
+ firstdigit = ptr += 2;
while (*ptr)
{
- if (isdigit((unsigned char) *ptr))
+ if (*ptr >= '0' && *ptr <= '1')
{
- if (unlikely(tmp > -(PG_INT32_MIN / 10)))
+ if (unlikely(tmp > -(PG_INT32_MIN / 2)))
goto out_of_range;
- tmp = tmp * 10 + (*ptr++ - '0');
+ tmp = tmp * 2 + (*ptr++ - '0');
}
else if (*ptr == '_')
{
- /* underscore may not be first */
- if (unlikely(ptr == firstdigit))
- goto invalid_syntax;
- /* and it must be followed by more digits */
+ /* underscore must be followed by more digits */
ptr++;
- if (*ptr == '\0' || !isdigit((unsigned char) *ptr))
+ if (*ptr == '\0' || *ptr < '0' || *ptr > '1')
goto invalid_syntax;
}
else
break;
}
}
+ else
+ goto invalid_syntax;
/* require at least one digit */
if (unlikely(ptr == firstdigit))
goto invalid_syntax;
/* allow trailing whitespace, but not other trailing chars */
- while (*ptr != '\0' && isspace((unsigned char) *ptr))
+ while (isspace((unsigned char) *ptr))
ptr++;
if (unlikely(*ptr != '\0'))