On Wed, 23 Nov 2022 at 21:54, David Rowley <[email protected]> wrote:
> I wonder if you'd be better off with something like:
>
> while (*ptr && isxdigit((unsigned char) *ptr))
> {
> if (unlikely(tmp & UINT64CONST(0xF000000000000000)))
> goto out_of_range;
>
> tmp = (tmp << 4) | hexlookup[(unsigned char) *ptr++];
> }
Here's a delta diff with it changed to work that way.
David
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index 2942b7c449..ce305b611d 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -136,13 +136,10 @@ pg_strtoint16(const char *s)
ptr += 2;
while (*ptr && isxdigit((unsigned char) *ptr))
{
- int8 digit = hexlookup[(unsigned char) *ptr];
-
- if (unlikely(pg_mul_s16_overflow(tmp, 16, &tmp)) ||
- unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0xF000))
goto out_of_range;
- ptr++;
+ tmp = (tmp << 4) | hexlookup[(unsigned char) *ptr++];
}
}
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
@@ -151,11 +148,10 @@ pg_strtoint16(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s16_overflow(tmp, 8, &tmp)) ||
- unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0xE000))
goto out_of_range;
+
+ tmp = (tmp << 3) | (*ptr++ - '0');
}
}
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
@@ -164,11 +160,10 @@ pg_strtoint16(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s16_overflow(tmp, 2, &tmp)) ||
- unlikely(pg_sub_s16_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0x8000))
goto out_of_range;
+
+ tmp = (tmp << 1) | (*ptr++ - '0');
}
}
else
@@ -255,13 +250,10 @@ pg_strtoint32(const char *s)
ptr += 2;
while (*ptr && isxdigit((unsigned char) *ptr))
{
- int8 digit = hexlookup[(unsigned char) *ptr];
-
- if (unlikely(pg_mul_s32_overflow(tmp, 16, &tmp)) ||
- unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0xF0000000))
goto out_of_range;
- ptr++;
+ tmp = (tmp << 4) | hexlookup[(unsigned char) *ptr++];
}
}
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
@@ -270,11 +262,10 @@ pg_strtoint32(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s32_overflow(tmp, 8, &tmp)) ||
- unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0xE0000000))
goto out_of_range;
+
+ tmp = (tmp << 3) | (*ptr++ - '0');
}
}
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
@@ -283,11 +274,10 @@ pg_strtoint32(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s32_overflow(tmp, 2, &tmp)) ||
- unlikely(pg_sub_s32_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & 0x80000000))
goto out_of_range;
+
+ tmp = (tmp << 1) | (*ptr++ - '0');
}
}
else
@@ -382,13 +372,10 @@ pg_strtoint64(const char *s)
ptr += 2;
while (*ptr && isxdigit((unsigned char) *ptr))
{
- int8 digit = hexlookup[(unsigned char) *ptr];
-
- if (unlikely(pg_mul_s64_overflow(tmp, 16, &tmp)) ||
- unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & UINT64CONST(0xF000000000000000)))
goto out_of_range;
- ptr++;
+ tmp = (tmp << 4) | hexlookup[(unsigned char) *ptr++];
}
}
else if (ptr[0] == '0' && (ptr[1] == 'o' || ptr[1] == 'O'))
@@ -397,11 +384,10 @@ pg_strtoint64(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '7'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s64_overflow(tmp, 8, &tmp)) ||
- unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & UINT64CONST(0xE000000000000000)))
goto out_of_range;
+
+ tmp = (tmp << 3) | (*ptr++ - '0');
}
}
else if (ptr[0] == '0' && (ptr[1] == 'b' || ptr[1] == 'B'))
@@ -410,11 +396,10 @@ pg_strtoint64(const char *s)
while (*ptr && (*ptr >= '0' && *ptr <= '1'))
{
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s64_overflow(tmp, 2, &tmp)) ||
- unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
+ if (unlikely(tmp & UINT64CONST(0x8000000000000000)))
goto out_of_range;
+
+ tmp = (tmp << 1) | (*ptr++ - '0');
}
}
else