On Wed, 23 Nov 2022 at 21:54, David Rowley <dgrowle...@gmail.com> 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

Reply via email to