*** a/.gitignore --- b/.gitignore *************** *** 34,36 **** lib*.pc --- 34,38 ---- /pgsql.sln.cache /Debug/ /Release/ + *.ll + *.ll.out *** a/src/backend/commands/view.c --- b/src/backend/commands/view.c *************** *** 342,347 **** UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) --- 342,348 ---- List *new_rt; RangeTblEntry *rt_entry1, *rt_entry2; + ParseState *pstate; /* * Make a copy of the given parsetree. It's not so much that we don't *************** *** 360,371 **** UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) * Create the 2 new range table entries and form the new range table... * OLD first, then NEW.... */ ! rt_entry1 = addRangeTableEntryForRelation(NULL, viewRel, makeAlias("old", NIL), false, false); ! rt_entry2 = addRangeTableEntryForRelation(NULL, viewRel, makeAlias("new", NIL), false, false); /* Must override addRangeTableEntry's default access-check flags */ rt_entry1->requiredPerms = 0; rt_entry2->requiredPerms = 0; --- 361,377 ---- * Create the 2 new range table entries and form the new range table... * OLD first, then NEW.... */ ! ! pstate = make_parsestate(NULL); ! ! rt_entry1 = addRangeTableEntryForRelation(pstate, viewRel, makeAlias("old", NIL), false, false); ! rt_entry2 = addRangeTableEntryForRelation(pstate, viewRel, makeAlias("new", NIL), false, false); + free_parsestate(pstate); + /* Must override addRangeTableEntry's default access-check flags */ rt_entry1->requiredPerms = 0; rt_entry2->requiredPerms = 0; *** a/src/backend/executor/execQual.c --- b/src/backend/executor/execQual.c *************** *** 3095,3105 **** ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, /* Get sub-array details from first member */ elem_ndims = this_ndims; ndims = elem_ndims + 1; ! if (ndims <= 0 || ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), ! errmsg("number of array dimensions (%d) exceeds " \ ! "the maximum allowed (%d)", ndims, MAXDIM))); elem_dims = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)); --- 3095,3106 ---- /* Get sub-array details from first member */ elem_ndims = this_ndims; ndims = elem_ndims + 1; ! ! if (INT32_ADD_OVERFLOWS(elem_ndims,1) || ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), ! errmsg("number of array dimensions (%d) exceeds " \ ! "the maximum allowed (%d)", ndims, MAXDIM))); elem_dims = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)); *** a/src/backend/optimizer/plan/subselect.c --- b/src/backend/optimizer/plan/subselect.c *************** *** 1168,1173 **** convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, --- 1168,1174 ---- Query *parse = root->parse; Query *subselect = (Query *) sublink->subselect; Relids upper_varnos; + ParseState *pstate; int rtindex; RangeTblEntry *rte; RangeTblRef *rtr; *************** *** 1212,1222 **** convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, * below). Therefore this is a lot easier than what pull_up_subqueries has * to go through. */ ! rte = addRangeTableEntryForSubquery(NULL, subselect, makeAlias("ANY_subquery", NIL), false, false); parse->rtable = lappend(parse->rtable, rte); rtindex = list_length(parse->rtable); --- 1213,1225 ---- * below). Therefore this is a lot easier than what pull_up_subqueries has * to go through. */ ! pstate = make_parsestate(NULL); ! rte = addRangeTableEntryForSubquery(pstate, subselect, makeAlias("ANY_subquery", NIL), false, false); + free_parsestate(pstate); parse->rtable = lappend(parse->rtable, rte); rtindex = list_length(parse->rtable); *** a/src/backend/parser/parse_relation.c --- b/src/backend/parser/parse_relation.c *************** *** 981,989 **** parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode) /* * Add an entry for a relation to the pstate's range table (p_rtable). * - * If pstate is NULL, we just build an RTE and return it without adding it - * to an rtable list. - * * Note: formerly this checked for refname conflicts, but that's wrong. * Caller is responsible for checking for conflicts in the appropriate scope. */ --- 981,986 ---- *************** *** 1002,1007 **** addRangeTableEntry(ParseState *pstate, --- 999,1006 ---- rte->rtekind = RTE_RELATION; rte->alias = alias; + Assert(pstate); + /* * Get the rel's OID. This access also ensures that we have an up-to-date * relcache entry for the rel. Since this is typically the first access *************** *** 1046,1053 **** addRangeTableEntry(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1045,1051 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1073,1078 **** addRangeTableEntryForRelation(ParseState *pstate, --- 1071,1078 ---- rte->relid = RelationGetRelid(rel); rte->relkind = rel->rd_rel->relkind; + Assert(pstate); + /* * Build the list of effective column names using user-supplied aliases * and/or actual column names. *************** *** 1099,1106 **** addRangeTableEntryForRelation(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1099,1105 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1125,1130 **** addRangeTableEntryForSubquery(ParseState *pstate, --- 1124,1131 ---- int varattno; ListCell *tlistitem; + Assert(pstate); + rte->rtekind = RTE_SUBQUERY; rte->relid = InvalidOid; rte->subquery = subquery; *************** *** 1177,1184 **** addRangeTableEntryForSubquery(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1178,1184 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1214,1219 **** addRangeTableEntryForFunction(ParseState *pstate, --- 1214,1221 ---- int natts, totalatts; + Assert(pstate); + rte->rtekind = RTE_FUNCTION; rte->relid = InvalidOid; rte->subquery = NULL; *************** *** 1431,1438 **** addRangeTableEntryForFunction(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1433,1439 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1456,1461 **** addRangeTableEntryForValues(ParseState *pstate, --- 1457,1464 ---- int numaliases; int numcolumns; + Assert(pstate); + rte->rtekind = RTE_VALUES; rte->relid = InvalidOid; rte->subquery = NULL; *************** *** 1503,1510 **** addRangeTableEntryForValues(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1506,1512 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1526,1531 **** addRangeTableEntryForJoin(ParseState *pstate, --- 1528,1535 ---- Alias *eref; int numaliases; + Assert(pstate); + /* * Fail if join has too many columns --- we must be able to reference any * of the columns with an AttrNumber. *************** *** 1571,1578 **** addRangeTableEntryForJoin(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1575,1581 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *************** *** 1597,1602 **** addRangeTableEntryForCTE(ParseState *pstate, --- 1600,1607 ---- int varattno; ListCell *lc; + Assert(pstate); + rte->rtekind = RTE_CTE; rte->ctename = cte->ctename; rte->ctelevelsup = levelsup; *************** *** 1671,1678 **** addRangeTableEntryForCTE(ParseState *pstate, * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! if (pstate != NULL) ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } --- 1676,1682 ---- * Add completed RTE to pstate's range table list, but not to join list * nor namespace --- caller must do that if appropriate. */ ! pstate->p_rtable = lappend(pstate->p_rtable, rte); return rte; } *** a/src/backend/storage/lmgr/proc.c --- b/src/backend/storage/lmgr/proc.c *************** *** 1120,1125 **** ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) --- 1120,1127 ---- */ do { + PGPROC *autovac; + PGSemaphoreLock(&MyProc->sem, true); /* *************** *** 1133,1141 **** ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) * If we are not deadlocked, but are waiting on an autovacuum-induced * task, send a signal to interrupt it. */ ! if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel) { - PGPROC *autovac = GetBlockingAutoVacuumPgproc(); PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno]; LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); --- 1135,1144 ---- * If we are not deadlocked, but are waiting on an autovacuum-induced * task, send a signal to interrupt it. */ ! if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && ! allow_autovacuum_cancel && ! (autovac = GetBlockingAutoVacuumPgproc())) { PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno]; LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); *** a/src/backend/utils/adt/array_userfuncs.c --- b/src/backend/utils/adt/array_userfuncs.c *************** *** 93,116 **** array_push(PG_FUNCTION_ARGS) if (arg0_elemid != InvalidOid) { /* append newelem */ - int ub = dimv[0] + lb[0] - 1; ! indx = ub + 1; ! /* overflow? */ ! if (indx < ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else { /* prepend newelem */ ! indx = lb[0] - 1; ! /* overflow? */ ! if (indx > lb[0]) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } } else if (ARR_NDIM(v) == 0) --- 93,117 ---- if (arg0_elemid != InvalidOid) { /* append newelem */ ! /* check for overflow in upper bound (indx+1) */ ! if (INT32_ADD_OVERFLOWS(dimv[0],lb[0]) || ! INT32_ADD_OVERFLOWS(dimv[0]+lb[0],1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + + indx = dimv[0] + lb[0]; } else { /* prepend newelem */ ! if (INT32_ADD_OVERFLOWS(lb[0],-1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + + indx = lb[0] - 1; } } else if (ARR_NDIM(v) == 0) *** a/src/backend/utils/adt/float.c --- b/src/backend/utils/adt/float.c *************** *** 2752,2763 **** width_bucket_float8(PG_FUNCTION_ARGS) result = 0; else if (operand >= bound2) { - result = count + 1; /* check for overflow */ ! if (result < count) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1; --- 2752,2763 ---- result = 0; else if (operand >= bound2) { /* check for overflow */ ! if (INT32_ADD_OVERFLOWS(count, 1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + result = count + 1; } else result = ((float8) count * (operand - bound1) / (bound2 - bound1)) + 1; *************** *** 2768,2779 **** width_bucket_float8(PG_FUNCTION_ARGS) result = 0; else if (operand <= bound2) { - result = count + 1; /* check for overflow */ ! if (result < count) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1; --- 2768,2779 ---- result = 0; else if (operand <= bound2) { /* check for overflow */ ! if (INT32_ADD_OVERFLOWS(count, 1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + result = count + 1; } else result = ((float8) count * (bound1 - operand) / (bound1 - bound2)) + 1; *** a/src/backend/utils/adt/int.c --- b/src/backend/utils/adt/int.c *************** *** 694,704 **** int4mul(PG_FUNCTION_ARGS) * 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); --- 694,700 ---- * the buck seems to be to check whether both inputs are in the int16 * range; if so, no overflow is possible. */ ! if (INT32_MUL_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); *************** *** 749,779 **** Datum int4inc(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); - int32 result; ! result = arg + 1; ! /* Overflow check */ ! if (arg > 0 && result < 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); ! PG_RETURN_INT32(result); } Datum 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); ! PG_RETURN_INT16(result); } Datum --- 745,769 ---- int4inc(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); ! if (INT32_ADD_OVERFLOWS(arg, 1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); ! PG_RETURN_INT32(arg + 1); } Datum int2um(PG_FUNCTION_ARGS) { int16 arg = PG_GETARG_INT16(0); ! if (arg == SHRT_MIN) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); ! PG_RETURN_INT16(-arg); } Datum *** a/src/backend/utils/adt/int8.c --- b/src/backend/utils/adt/int8.c *************** *** 102,120 **** scanint8(const char *str, bool errorOK, int64 *result) /* 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 bigint", ! str))); } ! tmp = newtmp; } gotdigits: --- 102,120 ---- /* process digits */ while (*ptr && isdigit((unsigned char) *ptr)) { ! if (INT64_MUL_OVERFLOWS(tmp, 10) || ! INT64_ADD_OVERFLOWS(tmp * 10, *ptr - '0')) { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), ! errmsg("value \"%s\" is out of range for type bigint", ! str))); } ! ! tmp = tmp * 10 + (*ptr++ - '0'); } gotdigits: *************** *** 490,504 **** Datum int8um(PG_FUNCTION_ARGS) { int64 arg = PG_GETARG_INT64(0); - int64 result; ! result = -arg; ! /* overflow check (needed for INT64_MIN) */ ! if (arg != 0 && SAMESIGN(result, arg)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } Datum --- 490,501 ---- int8um(PG_FUNCTION_ARGS) { int64 arg = PG_GETARG_INT64(0); ! if (arg == INT64_MIN) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(-arg); } Datum *************** *** 518,529 **** int8pl(PG_FUNCTION_ARGS) 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); --- 515,522 ---- result = arg1 + arg2; ! /* Overflow check. */ ! if (INT64_ADD_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); *************** *** 540,550 **** int8mi(PG_FUNCTION_ARGS) 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); --- 533,541 ---- result = arg1 - arg2; /* ! * Overflow check. */ ! if (INT64_SUB_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); *************** *** 558,585 **** int8mul(PG_FUNCTION_ARGS) 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"))); - } PG_RETURN_INT64(result); } --- 549,561 ---- int64 arg2 = PG_GETARG_INT64(1); int64 result; + if (INT64_MUL_OVERFLOWS(arg1, arg2)) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("bigint out of range"))); + result = arg1 * arg2; PG_RETURN_INT64(result); } *************** *** 607,618 **** int8div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { ! result = -arg1; ! /* overflow check (needed for INT64_MIN) */ ! if (arg1 != 0 && SAMESIGN(result, arg1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); PG_RETURN_INT64(result); } --- 583,594 ---- */ if (arg2 == -1) { ! if (arg1 == INT64_MIN) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); + + result = -arg1; PG_RETURN_INT64(result); } *************** *** 632,643 **** int8abs(PG_FUNCTION_ARGS) int64 arg1 = PG_GETARG_INT64(0); int64 result; ! result = (arg1 < 0) ? -arg1 : arg1; ! /* overflow check (needed for INT64_MIN) */ ! if (result < 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); PG_RETURN_INT64(result); } --- 608,619 ---- int64 arg1 = PG_GETARG_INT64(0); int64 result; ! if (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); } *************** *** 687,701 **** int8inc(PG_FUNCTION_ARGS) if (AggCheckCallContext(fcinfo, NULL)) { int64 *arg = (int64 *) PG_GETARG_POINTER(0); ! int64 result; ! result = *arg + 1; ! /* Overflow check */ ! if (result < 0 && *arg > 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! *arg = result; PG_RETURN_POINTER(arg); } --- 663,675 ---- if (AggCheckCallContext(fcinfo, NULL)) { int64 *arg = (int64 *) PG_GETARG_POINTER(0); ! int64 result = *arg; ! if (INT64_ADD_OVERFLOWS(result, 1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! result += 1; *arg = result; PG_RETURN_POINTER(arg); } *************** *** 704,719 **** int8inc(PG_FUNCTION_ARGS) { /* Not called as an aggregate, so just do it the dumb way */ int64 arg = PG_GETARG_INT64(0); - int64 result; ! result = arg + 1; ! /* Overflow check */ ! if (result < 0 && arg > 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! ! PG_RETURN_INT64(result); } } --- 678,689 ---- { /* Not called as an aggregate, so just do it the dumb way */ int64 arg = PG_GETARG_INT64(0); ! if (INT64_ADD_OVERFLOWS(arg, 1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(arg + 1); } } *************** *** 768,787 **** int84pl(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } Datum --- 738,750 ---- { int64 arg1 = PG_GETARG_INT64(0); int32 arg2 = PG_GETARG_INT32(1); ! if (INT64_ADD_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! ! PG_RETURN_INT64(arg1 + arg2); } Datum *************** *** 789,808 **** int84mi(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } Datum --- 752,764 ---- { int64 arg1 = PG_GETARG_INT64(0); int32 arg2 = PG_GETARG_INT32(1); ! if (INT64_SUB_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! ! PG_RETURN_INT64(arg1 - arg2); } Datum *************** *** 810,835 **** int84mul(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); 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) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } Datum --- 766,778 ---- { int64 arg1 = PG_GETARG_INT64(0); int32 arg2 = PG_GETARG_INT32(1); ! if (INT64_MUL_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! ! PG_RETURN_INT64(arg1 * arg2); } Datum *************** *** 856,868 **** int84div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { ! result = -arg1; ! /* overflow check (needed for INT64_MIN) */ ! if (arg1 != 0 && SAMESIGN(result, arg1)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } /* No overflow is possible */ --- 799,809 ---- */ if (arg2 == -1) { ! if (arg1 == INT64_MIN) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(-arg1); } /* No overflow is possible */ *************** *** 877,896 **** int48pl(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); 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)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(result); } Datum --- 818,829 ---- { int32 arg1 = PG_GETARG_INT32(0); int64 arg2 = PG_GETARG_INT64(1); ! if (INT64_ADD_OVERFLOWS(arg1, arg2)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); ! PG_RETURN_INT64(arg1 + arg2); } Datum *** a/src/backend/utils/adt/numeric.c --- b/src/backend/utils/adt/numeric.c *************** *** 3943,3950 **** numericvar_to_int8(NumericVar *var, int64 *result) int ndigits; int weight; int i; ! int64 val, ! oldval; bool neg; NumericVar rounded; --- 3943,3949 ---- int ndigits; int weight; int i; ! int64 val; bool neg; NumericVar rounded; *************** *** 3970,4006 **** numericvar_to_int8(NumericVar *var, int64 *result) weight = rounded.weight; Assert(weight >= 0 && ndigits <= weight + 1); ! /* Construct the result */ digits = rounded.digits; neg = (rounded.sign == NUMERIC_NEG); ! val = digits[0]; for (i = 1; i <= weight; i++) { ! oldval = val; ! val *= NBASE; ! if (i < ndigits) ! val += digits[i]; ! ! /* ! * 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 (!neg || (-val) != val || val == 0 || oldval < 0) { free_var(&rounded); return false; } ! } } free_var(&rounded); ! *result = neg ? -val : val; return true; } --- 3969,4003 ---- weight = rounded.weight; Assert(weight >= 0 && ndigits <= weight + 1); ! /* Construct the result. ! * ! * Accumulate the absolute value in "val" as a negative value to avoid ! * overflow with INT64_MIN. ! */ digits = rounded.digits; neg = (rounded.sign == NUMERIC_NEG); ! val = -digits[0]; for (i = 1; i <= weight; i++) { ! NumericDigit digit = (i < ndigits) ? digits[i] : 0; ! if (INT64_MUL_OVERFLOWS(val, NBASE) || ! INT64_SUB_OVERFLOWS(val*NBASE, digit)) { free_var(&rounded); return false; } ! val = val * NBASE - digit; } free_var(&rounded); ! if (!neg && val == INT64_MIN) ! /* overflows signed int64 */ ! return false; ! else if (!neg) ! *result = -val; ! else ! *result = val; return true; } *** a/src/backend/utils/adt/oracle_compat.c --- b/src/backend/utils/adt/oracle_compat.c *************** *** 15,20 **** --- 15,22 ---- */ #include "postgres.h" + #include + #include "utils/builtins.h" #include "utils/formatting.h" #include "mb/pg_wchar.h" *************** *** 175,188 **** lpad(PG_FUNCTION_ARGS) if (s2len <= 0) len = s1len; /* nothing to pad with, so don't pad */ - bytelen = pg_database_encoding_max_length() * len; - /* check for integer overflow */ ! if (len != 0 && bytelen / pg_database_encoding_max_length() != len) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested length too large"))); ret = (text *) palloc(VARHDRSZ + bytelen); m = len - s1len; --- 177,190 ---- if (s2len <= 0) len = s1len; /* nothing to pad with, so don't pad */ /* check for integer overflow */ ! if (len > INT_MAX / pg_database_encoding_max_length() - VARHDRSZ) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested length too large"))); + bytelen = pg_database_encoding_max_length() * len; + ret = (text *) palloc(VARHDRSZ + bytelen); m = len - s1len; *************** *** 1030,1052 **** repeat(PG_FUNCTION_ARGS) char *cp, *sp; if (count < 0) 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"))); ! } result = (text *) palloc(tlen); --- 1032,1051 ---- char *cp, *sp; + slen = VARSIZE_ANY_EXHDR(string); + if (count < 0) count = 0; ! else if (slen != 0 && count > (INT_MAX-VARHDRSZ) / slen) ! /* The palloc will actually fail at a lower value but we must protect ! * against signed integer overflow separately ! */ ! ereport(ERROR, ! (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), ! errmsg("requested length too large"))); ! tlen = VARHDRSZ + (count * slen); result = (text *) palloc(tlen); *** a/src/backend/utils/adt/varbit.c --- b/src/backend/utils/adt/varbit.c *************** *** 1026,1041 **** bitsubstring(VarBit *arg, int32 s, int32 l, bool length_not_specified) } else { ! e = s + l; ! ! /* ! * A negative value for L is the only way for the end position to be ! * before the start. SQL99 says to throw an error. ! */ ! if (e < s) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); e1 = Min(e, bitlen + 1); } if (s1 > bitlen || e1 <= s1) --- 1026,1037 ---- } else { ! /* SQL99 says to throw an error. */ ! if (l < 0) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); + e = s + l; e1 = Min(e, bitlen + 1); } if (s1 > bitlen || e1 <= s1) *************** *** 1138,1149 **** bit_overlay(VarBit *t1, VarBit *t2, int sp, int sl) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! sp_pl_sl = sp + sl; ! if (sp_pl_sl <= sl) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); s1 = bitsubstring(t1, 1, sp - 1, false); s2 = bitsubstring(t1, sp_pl_sl, -1, true); result = bit_catenate(s1, t2); --- 1134,1147 ---- ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! ! if (INT32_ADD_OVERFLOWS(sp, sl)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + sp_pl_sl = sp + sl; + s1 = bitsubstring(t1, 1, sp - 1, false); s2 = bitsubstring(t1, sp_pl_sl, -1, true); result = bit_catenate(s1, t2); *** a/src/backend/utils/adt/varlena.c --- b/src/backend/utils/adt/varlena.c *************** *** 782,813 **** text_substring(Datum str, int32 start, int32 length, bool length_not_specified) { S1 = Max(S, 1); ! if (length_not_specified) /* special case - get length to end of ! * string */ L1 = -1; else { ! /* end position */ ! int E = S + length; ! /* ! * A negative value for L is the only way for the end position to ! * be before the start. SQL99 says to throw an error. ! */ ! if (E < S) ! ereport(ERROR, ! (errcode(ERRCODE_SUBSTRING_ERROR), ! errmsg("negative substring length not allowed"))); ! /* ! * A zero or negative value for the end position can happen if the ! * start was negative or one. SQL99 says to return a zero-length ! * string. ! */ ! if (E < 1) return cstring_to_text(""); - - L1 = E - S1; } /* --- 782,813 ---- { S1 = Max(S, 1); ! /* special case - get length to end of string */ ! if (length_not_specified) L1 = -1; + + else if (length < 0) + /* SQL99 says to throw an error. */ + ereport(ERROR, + (errcode(ERRCODE_SUBSTRING_ERROR), + errmsg("negative substring length not allowed"))); + + else if (INT_MAX - length < start) + /* overflow (but the string can't be that large so just get length + * to end of string) */ + L1 = -1; + else { ! /* Calculate length adjusted to actual start of string (input ! * start could have been negative) and note that according to ! * SQL99 we should return an empty string if the entire string is ! * left of 1 */ ! L1 = S + length - S1; ! if (L1 <= 0) return cstring_to_text(""); } /* *************** *** 847,869 **** text_substring(Datum str, int32 start, int32 length, bool length_not_specified) */ slice_start = 0; ! if (length_not_specified) /* special case - get length to end of ! * string */ slice_size = L1 = -1; else { int E = S + length; /* - * A negative value for L is the only way for the end position to - * be before the start. SQL99 says to throw an error. - */ - if (E < S) - ereport(ERROR, - (errcode(ERRCODE_SUBSTRING_ERROR), - errmsg("negative substring length not allowed"))); - - /* * A zero or negative value for the end position can happen if the * start was negative or one. SQL99 says to return a zero-length * string. --- 847,872 ---- */ slice_start = 0; ! if (length_not_specified) ! /* special case - get length to end of string */ ! slice_size = L1 = -1; ! ! else if (length < 0) ! /* SQL99 says to throw an error. */ ! ereport(ERROR, ! (errcode(ERRCODE_SUBSTRING_ERROR), ! errmsg("negative substring length not allowed"))); ! ! else if (INT_MAX - length < start) ! /* overflow but the string can't be that large so just get length ! * to end of string */ slice_size = L1 = -1; + else { int E = S + length; /* * A zero or negative value for the end position can happen if the * start was negative or one. SQL99 says to return a zero-length * string. *************** *** 1006,1017 **** text_overlay(text *t1, text *t2, int sp, int sl) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! sp_pl_sl = sp + sl; ! if (sp_pl_sl <= sl) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); s1 = text_substring(PointerGetDatum(t1), 1, sp - 1, false); s2 = text_substring(PointerGetDatum(t1), sp_pl_sl, -1, true); result = text_catenate(s1, t2); --- 1009,1022 ---- ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! ! if (INT_MAX - sp < sl) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + sp_pl_sl = sp + sl; + s1 = text_substring(PointerGetDatum(t1), 1, sp - 1, false); s2 = text_substring(PointerGetDatum(t1), sp_pl_sl, -1, true); result = text_catenate(s1, t2); *************** *** 1949,1969 **** bytea_substring(Datum str, */ L1 = -1; } else { /* end position */ int E = S + L; /* - * A negative value for L is the only way for the end position to be - * before the start. SQL99 says to throw an error. - */ - if (E < S) - ereport(ERROR, - (errcode(ERRCODE_SUBSTRING_ERROR), - errmsg("negative substring length not allowed"))); - - /* * A zero or negative value for the end position can happen if the * start was negative or one. SQL99 says to return a zero-length * string. --- 1954,1976 ---- */ L1 = -1; } + else if (L < 0) + /* SQL99 says to throw an error. */ + ereport(ERROR, + (errcode(ERRCODE_SUBSTRING_ERROR), + errmsg("negative substring length not allowed"))); + + else if (INT_MAX - L < S) + /* Overflow, but the string can't be so large so just fetch to end of + * the string. */ + L1 = -1; + else { /* end position */ int E = S + L; /* * A zero or negative value for the end position can happen if the * start was negative or one. SQL99 says to return a zero-length * string. *************** *** 2029,2040 **** bytea_overlay(bytea *t1, bytea *t2, int sp, int sl) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! sp_pl_sl = sp + sl; ! if (sp_pl_sl <= sl) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); s1 = bytea_substring(PointerGetDatum(t1), 1, sp - 1, false); s2 = bytea_substring(PointerGetDatum(t1), sp_pl_sl, -1, true); result = bytea_catenate(s1, t2); --- 2036,2049 ---- ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); ! ! if (INT_MAX - sp < sl) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + sp_pl_sl = sp + sl; + s1 = bytea_substring(PointerGetDatum(t1), 1, sp - 1, false); s2 = bytea_substring(PointerGetDatum(t1), sp_pl_sl, -1, true); result = bytea_catenate(s1, t2); *** a/src/include/c.h --- b/src/include/c.h *************** *** 81,86 **** --- 81,87 ---- #include #endif #include + #include #include #if defined(WIN32) || defined(__CYGWIN__) *************** *** 272,277 **** typedef long int int64; --- 273,285 ---- #ifndef HAVE_UINT64 typedef unsigned long int uint64; #endif + #ifndef INT64_MAX + #define INT64_MAX LONG_MAX + #endif + #ifndef INT64_MIN + #define INT64_MIN LONG_MIN + #endif + #elif defined(HAVE_LONG_LONG_INT_64) /* We have working support for "long long int", use that */ *************** *** 281,286 **** typedef long long int int64; --- 289,309 ---- #ifndef HAVE_UINT64 typedef unsigned long long int uint64; #endif + #ifndef INT64_MAX + #ifdef LLONG_MAX + #define INT64_MAX LLONG_MAX + #else + #define INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF) + #endif + #endif + #ifndef INT64_MIN + #ifdef LLONG_MIN + #define INT64_MIN LLONG_MIN + #else + #define INT64_MIN (-INT64_MAX-1) + #endif + #endif + #else /* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */ #error must have a working 64-bit integer datatype *************** *** 713,718 **** typedef NameData *Name; --- 736,808 ---- #define Abs(x) ((x) >= 0 ? (x) : -(x)) /* + * Detect overflow for signed INT32 and INT64 + * + * Note that this has to be done before doing the suspect arithmetic rather + * than afterwards by examining the signs because signed overflow is not well + * defined and compilers take liberties to optimize away the checks. + * + * Also note that SUB_OVERFLOWS is not just the same as doing ADD_OVERFLOWS + * with -b because if b = INT_MIN then that would itself cause an overflow... + */ + + + #define INT32_ADD_OVERFLOWS(a,b) ( \ + ((a)>0 && (b)>0 && (a) > INT_MAX - (b)) || \ + ((a)<0 && (b)<0 && (a) < INT_MIN - (b)) \ + ) + + #define INT32_SUB_OVERFLOWS(a,b) ( \ + ((a)<0 && (b)>0 && (a) < INT_MIN + (b)) || \ + ((a)>0 && (b)<0 && (a) > INT_MAX + (b)) \ + ) + + #define INT64_ADD_OVERFLOWS(a,b) ( \ + ((a)>0 && (b)>0 && (a) > INT64_MAX - (b)) || \ + ((a)<0 && (b)<0 && (a) < INT64_MIN - (b)) \ + ) + + #define INT64_SUB_OVERFLOWS(a,b) ( \ + ((a)<0 && (b)>0 && (a) < INT64_MIN + (b)) || \ + ((a)>0 && (b)<0 && (a) > INT64_MAX + (b)) \ + ) + + /* Overflow can only happen if at least one value is outside the range + * sqrt(min)..sqrt(max) so check that first as the division can be quite a bit + * more expensive than the multiplication. + * + * Multiplying by 0 or 1 can't overflow of course and checking for 0 + * separately avoids any risk of dividing by 0. Be careful about dividing + * INT_MIN by -1 also, note reversing the a and b to ensure we're always + * dividing it by a positive value. + * + */ + + #define INT32_MUL_OVERFLOWS(a,b) ( \ + ((a) > SHRT_MAX || (a) < SHRT_MIN || \ + (b) > SHRT_MAX || (b) < SHRT_MIN) && \ + (a) != 0 && (a) != 1 && (b) != 0 && (b) != 1 && \ + ( \ + ((a) > 0 && (b) > 0 && (a) > INT_MAX / (b)) || \ + ((a) > 0 && (b) < 0 && (b) < INT_MIN / (a)) || \ + ((a) < 0 && (b) > 0 && (a) < INT_MIN / (b)) || \ + ((a) < 0 && (b) < 0 && (a) < INT_MAX / (b)) \ + ) \ + ) + + #define INT64_MUL_OVERFLOWS(a,b) ( \ + ((a) > INT_MAX || (a) < INT_MIN || \ + (b) > INT_MAX || (b) < INT_MIN) && \ + (a) != 0 && (a) != 1 && (b) != 0 && (b) != 1 && \ + ( \ + ((a) > 0 && (b) > 0 && (a) > INT64_MAX / (b)) || \ + ((a) > 0 && (b) < 0 && (b) < INT64_MIN / (a)) || \ + ((a) < 0 && (b) > 0 && (a) < INT64_MIN / (b)) || \ + ((a) < 0 && (b) < 0 && (a) < INT64_MAX / (b)) \ + ) \ + ) + + /* * StrNCpy * Like standard library function strncpy(), except that result string * is guaranteed to be null-terminated --- that is, at most N-1 bytes *** a/src/pl/plpgsql/src/pl_exec.c --- b/src/pl/plpgsql/src/pl_exec.c *************** *** 2036,2048 **** exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt) */ if (stmt->reverse) { ! if ((int32) (loop_value - step_value) > loop_value) break; loop_value -= step_value; } else { ! if ((int32) (loop_value + step_value) < loop_value) break; loop_value += step_value; } --- 2036,2048 ---- */ if (stmt->reverse) { ! if (INT32_SUB_OVERFLOWS(loop_value, step_value)) break; loop_value -= step_value; } else { ! if (INT32_ADD_OVERFLOWS(loop_value, step_value)) break; loop_value += step_value; } *** a/src/timezone/localtime.c --- b/src/timezone/localtime.c *************** *** 1278,1294 **** timesub(const pg_time_t *timep, long offset, } /* ! * Simplified normalize logic courtesy Paul Eggert. */ static int increment_overflow(int *number, int delta) { ! int number0; - number0 = *number; *number += delta; ! return (*number < number0) != (delta < 0); } /* --- 1278,1297 ---- } /* ! * signed overflow cannot be detected by looking for wraparound after the fact ! * as newer compilers optimize away such checks. Return 1 if overflow would ! * occur and 0 otherwise. */ static int increment_overflow(int *number, int delta) { ! if ((delta > 0 && *number > INT_MAX - delta) || ! (delta < 0 && *number < INT_MIN - delta)) ! return 1; *number += delta; ! return 0; } /* *** a/src/timezone/zic.c --- b/src/timezone/zic.c *************** *** 2651,2683 **** getfields(char *cp) static long oadd(long t1, long t2) { ! long t; ! ! t = t1 + t2; ! if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) ! { error(_("time overflow")); exit(EXIT_FAILURE); } ! return t; } static zic_t tadd(const zic_t t1, long t2) { - zic_t t; - if (t1 == max_time && t2 > 0) return max_time; if (t1 == min_time && t2 < 0) return min_time; ! t = t1 + t2; ! if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) ! { error(_("time overflow")); exit(EXIT_FAILURE); } ! return t; } /* --- 2651,2677 ---- static long oadd(long t1, long t2) { ! if (t1 < 0 ? t2 < LONG_MIN - t1 : LONG_MAX - t1 < t2) { error(_("time overflow")); exit(EXIT_FAILURE); } ! ! return t1 + t2; } static zic_t tadd(const zic_t t1, long t2) { if (t1 == max_time && t2 > 0) return max_time; if (t1 == min_time && t2 < 0) return min_time; ! if (t1 < 0 ? t2 < min_time - t1 : max_time - t1 < t2) { error(_("time overflow")); exit(EXIT_FAILURE); } ! ! return t1 + t2; } /*