#include "btree_gist.h"
#include "btree_utils_num.h"
+#include "common/int.h"
#include "utils/cash.h"
typedef struct
Cash r;
Cash ra;
- r = a - b;
- ra = Abs(r);
-
- /* Overflow check. */
- if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ if (pg_sub_s64_overflow(a, b, &r) ||
+ r == INT64_MIN)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("money out of range")));
+ ra = Abs(r);
+
PG_RETURN_CASH(ra);
}
#include "btree_gist.h"
#include "btree_utils_num.h"
+#include "common/int.h"
typedef struct int16key
{
int16 r;
int16 ra;
- r = a - b;
- ra = Abs(r);
-
- /* Overflow check. */
- if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ if (pg_sub_s16_overflow(a, b, &r) ||
+ r == INT16_MIN)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
+ ra = Abs(r);
+
PG_RETURN_INT16(ra);
}
#include "btree_gist.h"
#include "btree_utils_num.h"
+#include "common/int.h"
typedef struct int32key
{
int32 r;
int32 ra;
- r = a - b;
- ra = Abs(r);
-
- /* Overflow check. */
- if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ if (pg_sub_s32_overflow(a, b, &r) ||
+ r == INT32_MIN)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
+ ra = Abs(r);
+
PG_RETURN_INT32(ra);
}
#include "btree_gist.h"
#include "btree_utils_num.h"
+#include "common/int.h"
typedef struct int64key
{
int64 r;
int64 ra;
- r = a - b;
- ra = Abs(r);
-
- /* Overflow check. */
- if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ if (pg_sub_s64_overflow(a, b, &r) ||
+ r == INT64_MIN)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ ra = Abs(r);
+
PG_RETURN_INT64(ra);
}
#define GET_FLOAT_DISTANCE(t, arg1, arg2) Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
-#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
-
/*
* check to see if a float4/8 val has underflowed or overflowed
* borrowed from src/backend/utils/adt/float.c
#include "postgres.h"
#include "catalog/pg_type.h"
+#include "common/int.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
if (eah->ndims == 1)
{
/* append newelem */
- int ub;
-
lb = eah->lbound;
dimv = eah->dims;
- ub = dimv[0] + lb[0] - 1;
- indx = ub + 1;
- /* overflow? */
- if (indx < ub)
+ /* index of added elem is at lb[0] + (dimv[0] - 1) + 1 */
+ if (pg_add_s32_overflow(lb[0], dimv[0], &indx))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
{
/* prepend newelem */
lb = eah->lbound;
- indx = lb[0] - 1;
lb0 = lb[0];
- /* overflow? */
- if (indx > lb[0])
+ if (pg_sub_s32_overflow(lb0, 1, &indx))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
#include <ctype.h>
#include <math.h>
+#include "common/int.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/cash.h"
for (; *s; s++)
{
- /* we look for digits as long as we have found less */
- /* than the required number of decimal places */
+ /*
+ * We look for digits as long as we have found less than the required
+ * number of decimal places.
+ */
if (isdigit((unsigned char) *s) && (!seen_dot || dec < fpoint))
{
- Cash newvalue = (value * 10) - (*s - '0');
+ int8 digit = *s - '0';
- if (newvalue / 10 != value)
+ if (pg_mul_s64_overflow(value, 10, &value) ||
+ pg_sub_s64_overflow(value, digit, &value))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value \"%s\" is out of range for type %s",
str, "money")));
- value = newvalue;
-
if (seen_dot)
dec++;
}
/* round off if there's another digit */
if (isdigit((unsigned char) *s) && *s >= '5')
- value--; /* remember we build the value in the negative */
-
- if (value > 0)
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("value \"%s\" is out of range for type %s",
- str, "money")));
+ {
+ /* remember we build the value in the negative */
+ if (pg_sub_s64_overflow(value, 1, &value))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type %s",
+ str, "money")));
+ }
/* adjust for less than required decimal places */
for (; dec < fpoint; dec++)
{
- Cash newvalue = value * 10;
-
- if (newvalue / 10 != value)
+ if (pg_mul_s64_overflow(value, 10, &value))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value \"%s\" is out of range for type %s",
str, "money")));
-
- value = newvalue;
}
/*
*/
if (sgn > 0)
{
- result = -value;
- if (result < 0)
+ if (value == PG_INT64_MIN)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value \"%s\" is out of range for type %s",
str, "money")));
+ result = -value;
}
else
result = value;
#include <limits.h>
#include "catalog/pg_type.h"
+#include "common/int.h"
#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
result = 0;
else if (operand >= bound2)
{
- result = count + 1;
- /* check for overflow */
- if (result < count)
+ if (pg_add_s32_overflow(count, 1, &result))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
result = 0;
else if (operand <= bound2)
{
- result = count + 1;
- /* check for overflow */
- if (result < count)
+ if (pg_add_s32_overflow(count, 1, &result))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
#include <limits.h>
#include "catalog/pg_type.h"
+#include "common/int.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
-
-#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
-
#define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
typedef struct
{
int32 arg1 = PG_GETARG_INT32(0);
- if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
+ if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
int4um(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
- int32 result;
- result = -arg;
- /* overflow check (needed for INT_MIN) */
- if (arg != 0 && SAMESIGN(result, arg))
+ if (unlikely(arg == PG_INT32_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
- PG_RETURN_INT32(result);
+ PG_RETURN_INT32(-arg);
}
Datum
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There are two cases where this fails: arg2 = 0 (which cannot
- * overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
- * overflow and thus incorrectly match).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int16
- * range; if so, no overflow is possible.
- */
- if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
- arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
- arg2 != 0 &&
- ((arg2 == -1 && arg1 < 0 && result < 0) ||
- result / arg2 != arg1))
+ if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == PG_INT32_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
+ result = -arg1;
PG_RETURN_INT32(result);
}
int32 arg = PG_GETARG_INT32(0);
int32 result;
- result = arg + 1;
- /* Overflow check */
- if (arg > 0 && result < 0)
+ if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int2um(PG_FUNCTION_ARGS)
{
int16 arg = PG_GETARG_INT16(0);
- int16 result;
- result = -arg;
- /* overflow check (needed for SHRT_MIN) */
- if (arg != 0 && SAMESIGN(result, arg))
+ if (unlikely(arg == PG_INT16_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
- PG_RETURN_INT16(result);
+ PG_RETURN_INT16(-arg);
}
Datum
int16 arg2 = PG_GETARG_INT16(1);
int16 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int16 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
{
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
- int32 result32;
-
- /*
- * The most practical way to detect overflow is to do the arithmetic in
- * int32 (so that the result can't overflow) and then do a range check.
- */
- result32 = (int32) arg1 * (int32) arg2;
+ int16 result;
- if (result32 < SHRT_MIN || result32 > SHRT_MAX)
+ if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
- PG_RETURN_INT16((int16) result32);
+ PG_RETURN_INT16(result);
}
Datum
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for SHRT_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT16_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
+ result = -arg1;
PG_RETURN_INT16(result);
}
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int32 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There is one case where this fails: arg2 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int16
- * range; if so, no overflow is possible.
- */
- if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
- result / arg2 != arg1)
+ if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
int16 arg2 = PG_GETARG_INT16(1);
int32 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int32 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int32 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg1 gives arg2
- * again. There is one case where this fails: arg1 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int16
- * range; if so, no overflow is possible.
- */
- if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
- result / arg1 != arg2)
+ if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int32 result;
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == PG_INT32_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
+ result = -arg1;
PG_RETURN_INT32(result);
}
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
int32 arg1 = PG_GETARG_INT32(0);
int32 result;
- result = (arg1 < 0) ? -arg1 : arg1;
- /* overflow check (needed for INT_MIN) */
- if (result < 0)
+ if (unlikely(arg1 == INT32_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
+ result = (arg1 < 0) ? -arg1 : arg1;
PG_RETURN_INT32(result);
}
int16 arg1 = PG_GETARG_INT16(0);
int16 result;
- result = (arg1 < 0) ? -arg1 : arg1;
- /* overflow check (needed for SHRT_MIN) */
- if (result < 0)
+ if (unlikely(arg1 == INT16_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
+ result = (arg1 < 0) ? -arg1 : arg1;
PG_RETURN_INT16(result);
}
if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
- /* increment current in preparation for next iteration */
- fctx->current += fctx->step;
-
- /* if next-value computation overflows, this is the final result */
- if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
+ /*
+ * Increment current in preparation for next iteration. If next-value
+ * computation overflows, this is the final result.
+ */
+ if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
fctx->step = 0;
/* do when there is more left to send */
#include <limits.h>
#include <math.h>
+#include "common/int.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/int8.h"
#define MAXINT8LEN 25
-#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
-
typedef struct
{
int64 current;
{
const char *ptr = str;
int64 tmp = 0;
- int sign = 1;
+ bool neg = false;
/*
* Do our own scan, rather than relying on sscanf which might be broken
* for long long.
+ *
+ * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
+ * value as a negative number.
*/
/* skip leading spaces */
if (*ptr == '-')
{
ptr++;
-
- /*
- * Do an explicit check for INT64_MIN. Ugly though this is, it's
- * cleaner than trying to get the loop below to handle it portably.
- */
- if (strncmp(ptr, "9223372036854775808", 19) == 0)
- {
- tmp = PG_INT64_MIN;
- ptr += 19;
- goto gotdigits;
- }
- sign = -1;
+ neg = true;
}
else if (*ptr == '+')
ptr++;
/* require at least one digit */
- if (!isdigit((unsigned char) *ptr))
+ if (unlikely(!isdigit((unsigned char) *ptr)))
{
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for integer: \"%s\"",
- str)));
+ goto invalid_syntax;
}
/* process digits */
while (*ptr && isdigit((unsigned char) *ptr))
{
- int64 newtmp = tmp * 10 + (*ptr++ - '0');
-
- if ((newtmp / 10) != tmp) /* overflow? */
- {
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("value \"%s\" is out of range for type %s",
- str, "bigint")));
- }
- tmp = newtmp;
- }
+ int8 digit = (*ptr++ - '0');
-gotdigits:
+ if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
+ unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
+ goto out_of_range;
+ }
/* allow trailing whitespace, but not other trailing chars */
while (*ptr != '\0' && isspace((unsigned char) *ptr))
ptr++;
- if (*ptr != '\0')
+ if (unlikely(*ptr != '\0'))
+ goto invalid_syntax;
+
+ if (!neg)
{
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for integer: \"%s\"",
- str)));
+ if (unlikely(tmp == INT64_MIN))
+ goto out_of_range;
+ tmp = -tmp;
}
-
- *result = (sign < 0) ? -tmp : tmp;
+ *result = tmp;
return true;
+
+out_of_range:
+ if (errorOK)
+ return false;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type %s",
+ str, "bigint")));
+invalid_syntax:
+ if (errorOK)
+ return false;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for integer: \"%s\"",
+ str)));
}
/* int8in()
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = -arg;
- /* overflow check (needed for INT64_MIN) */
- if (arg != 0 && SAMESIGN(result, arg))
+ if (unlikely(arg == PG_INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg;
PG_RETURN_INT64(result);
}
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There are two cases where this fails: arg2 = 0 (which cannot
- * overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division itself
- * will overflow and thus incorrectly match).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) || arg2 != (int64) ((int32) arg2))
- {
- if (arg2 != 0 &&
- ((arg2 == -1 && arg1 < 0 && result < 0) ||
- result / arg2 != arg1))
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("bigint out of range")));
- }
+ if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
PG_RETURN_INT64(result);
}
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
int64 arg1 = PG_GETARG_INT64(0);
int64 result;
- result = (arg1 < 0) ? -arg1 : arg1;
- /* overflow check (needed for INT64_MIN) */
- if (result < 0)
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = (arg1 < 0) ? -arg1 : arg1;
PG_RETURN_INT64(result);
}
int64 arg1 = PG_GETARG_INT64(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
if (AggCheckCallContext(fcinfo, NULL))
{
int64 *arg = (int64 *) PG_GETARG_POINTER(0);
- int64 result;
- result = *arg + 1;
- /* Overflow check */
- if (result < 0 && *arg > 0)
+ if (unlikely(pg_add_s64_overflow(*arg, 1, arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
- *arg = result;
PG_RETURN_POINTER(arg);
}
else
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = arg + 1;
- /* Overflow check */
- if (result < 0 && arg > 0)
+ if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
if (AggCheckCallContext(fcinfo, NULL))
{
int64 *arg = (int64 *) PG_GETARG_POINTER(0);
- int64 result;
- result = *arg - 1;
- /* Overflow check */
- if (result > 0 && *arg < 0)
+ if (unlikely(pg_sub_s64_overflow(*arg, 1, arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
-
- *arg = result;
PG_RETURN_POINTER(arg);
}
else
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = arg - 1;
- /* Overflow check */
- if (result > 0 && arg < 0)
+ if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg1 gives arg2
- * again. There is one case where this fails: arg1 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) &&
- result / arg1 != arg2)
+ if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There is one case where this fails: arg2 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg2 != (int64) ((int32) arg2) &&
- result / arg2 != arg1)
+ if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int32 arg1 = PG_GETARG_INT32(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg1 gives arg2
- * again. There is one case where this fails: arg1 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) &&
- result / arg1 != arg2)
+ if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There is one case where this fails: arg2 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg2 != (int64) ((int32) arg2) &&
- result / arg2 != arg1)
+ if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
int16 arg1 = PG_GETARG_INT16(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
int84(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- int32 result;
-
- result = (int32) arg;
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
- PG_RETURN_INT32(result);
+ PG_RETURN_INT32((int32) arg);
}
Datum
int82(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- int16 result;
- result = (int16) arg;
-
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
- PG_RETURN_INT16(result);
+ PG_RETURN_INT16((int16) arg);
}
Datum
/* Round arg to nearest integer (but it's still in float form) */
arg = rint(arg);
- /*
- * Does it fit in an int64? Avoid assuming that we have handy constants
- * defined for the range boundaries, instead test for overflow by
- * reverse-conversion.
- */
- result = (int64) arg;
-
- if ((float8) result != arg)
+ if (unlikely(arg < (double) PG_INT64_MIN) ||
+ unlikely(arg > (double) PG_INT64_MAX) ||
+ unlikely(isnan(arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = (int64) arg;
+
PG_RETURN_INT64(result);
}
ftoi8(PG_FUNCTION_ARGS)
{
float4 arg = PG_GETARG_FLOAT4(0);
- int64 result;
float8 darg;
/* Round arg to nearest integer (but it's still in float form) */
darg = rint(arg);
- /*
- * Does it fit in an int64? Avoid assuming that we have handy constants
- * defined for the range boundaries, instead test for overflow by
- * reverse-conversion.
- */
- result = (int64) darg;
-
- if ((float8) result != darg)
+ if (unlikely(arg < (float4) PG_INT64_MIN) ||
+ unlikely(arg > (float4) PG_INT64_MAX) ||
+ unlikely(isnan(arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
- PG_RETURN_INT64(result);
+ PG_RETURN_INT64((int64) darg);
}
Datum
i8tooid(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- Oid result;
-
- result = (Oid) arg;
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("OID out of range")));
- PG_RETURN_OID(result);
+ PG_RETURN_OID((Oid) arg);
}
Datum
if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
- /* increment current in preparation for next iteration */
- fctx->current += fctx->step;
-
- /* if next-value computation overflows, this is the final result */
- if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
+ /*
+ * Increment current in preparation for next iteration. If next-value
+ * computation overflows, this is the final result.
+ */
+ if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
fctx->step = 0;
/* do when there is more left to send */
#include "access/hash.h"
#include "catalog/pg_type.h"
+#include "common/int.h"
#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
int ndigits;
int weight;
int i;
- int64 val,
- oldval;
+ int64 val;
bool neg;
NumericVar rounded;
weight = rounded.weight;
Assert(weight >= 0 && ndigits <= weight + 1);
- /* Construct the result */
+ /*
+ * Construct the result. To avoid issues with converting a value
+ * corresponding to INT64_MIN (which can't be represented as a positive 64
+ * bit two's complement integer), accumulate value as a negative number.
+ */
digits = rounded.digits;
neg = (rounded.sign == NUMERIC_NEG);
- val = digits[0];
+ val = -digits[0];
for (i = 1; i <= weight; i++)
{
- oldval = val;
- val *= NBASE;
- if (i < ndigits)
- val += digits[i];
+ if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
+ {
+ free_var(&rounded);
+ return false;
+ }
- /*
- * The overflow check is a bit tricky because we want to accept
- * INT64_MIN, which will overflow the positive accumulator. We can
- * detect this case easily though because INT64_MIN is the only
- * nonzero value for which -val == val (on a two's complement machine,
- * anyway).
- */
- if ((val / NBASE) != oldval) /* possible overflow? */
+ if (i < ndigits)
{
- if (!neg || (-val) != val || val == 0 || oldval < 0)
+ if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
{
free_var(&rounded);
return false;
free_var(&rounded);
- *result = neg ? -val : val;
+ if (!neg)
+ {
+ if (unlikely(val == INT64_MIN))
+ return false;
+ val = -val;
+ }
+ *result = val;
+
return true;
}
*/
#include "postgres.h"
+#include "common/int.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "mb/pg_wchar.h"
count = 0;
slen = VARSIZE_ANY_EXHDR(string);
- tlen = VARHDRSZ + (count * slen);
- /* Check for integer overflow */
- if (slen != 0 && count != 0)
- {
- int check = count * slen;
- int check2 = check + VARHDRSZ;
-
- if ((check / slen) != count || check2 <= check)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("requested length too large")));
- }
+ if (unlikely(pg_mul_s32_overflow(count, slen, &tlen)) ||
+ unlikely(pg_add_s32_overflow(tlen, VARHDRSZ, &tlen)))
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("requested length too large")));
result = (text *) palloc(tlen);
#include "postgres.h"
#include "access/htup_details.h"
+#include "common/int.h"
#include "libpq/pqformat.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
ereport(ERROR,
(errcode(ERRCODE_SUBSTRING_ERROR),
errmsg("negative substring length not allowed")));
- sp_pl_sl = sp + sl;
- if (sp_pl_sl <= sl)
+ if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
#include "access/tuptoaster.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
+#include "common/int.h"
#include "common/md5.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
ereport(ERROR,
(errcode(ERRCODE_SUBSTRING_ERROR),
errmsg("negative substring length not allowed")));
- sp_pl_sl = sp + sl;
- if (sp_pl_sl <= sl)
+ if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
ereport(ERROR,
(errcode(ERRCODE_SUBSTRING_ERROR),
errmsg("negative substring length not allowed")));
- sp_pl_sl = sp + sl;
- if (sp_pl_sl <= sl)
+ if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
while (*cp >= '0' && *cp <= '9')
{
- int newval = val * 10 + (*cp - '0');
+ int8 digit = (*cp - '0');
- if (newval / 10 != val) /* overflow? */
+ if (unlikely(pg_mul_s32_overflow(val, 10, &val)) ||
+ unlikely(pg_add_s32_overflow(val, digit, &val)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("number is out of range")));
- val = newval;
ADVANCE_PARSE_POINTER(cp, end_ptr);
found = true;
}