Hi,

The money type has overflow handling in its input function:
Datum
cash_in(PG_FUNCTION_ARGS)
...
                        Cash            newvalue = (value * 10) - (*s - '0');

                        if (newvalue / 10 != value)
                                ereport(ERROR,
                                                
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                                 errmsg("value \"%s\" is out of 
range for type %s",
                                                                str, "money")));

but not in a lot of other relevant places:

Datum
cash_pl(PG_FUNCTION_ARGS)
{
        Cash            c1 = PG_GETARG_CASH(0);
        Cash            c2 = PG_GETARG_CASH(1);
        Cash            result;

        result = c1 + c2;

        PG_RETURN_CASH(result);
}

Same with cash_mi, int8_mul_cash, cash_div_int8, etc.

cash_out doesn't have a plain overflow, but:
        if (value < 0)
        {
                /* make the amount positive for digit-reconstruction loop */
                value = -value;

doesn't reliably work if value is PG_INT64_MIN.


This leads to fun like:

postgres[2002][1]=# SELECT '92233720368547758.07'::money+'0.1';
┌─────────────────────────────┐
│          ?column?           │
├─────────────────────────────┤
│ -$92,233,720,368,547,757.99 │
└─────────────────────────────┘



Greetings,

Andres Freund

Reply via email to