Re: avoid negating LONG_MIN in cash_out() - Mailing list pgsql-hackers

From Zhihong Yu
Subject Re: avoid negating LONG_MIN in cash_out()
Date
Msg-id CALNJ-vQ0VfOL7qj3R+uaxdtRFZjDJJzdzeT5ocUyqoSW+5pyPA@mail.gmail.com
Whole thread Raw
In response to Re: avoid negating LONG_MIN in cash_out()  (Zhihong Yu <zyu@yugabyte.com>)
Responses Re: avoid negating LONG_MIN in cash_out()
List pgsql-hackers


On Thu, Aug 11, 2022 at 10:55 AM Zhihong Yu <zyu@yugabyte.com> wrote:


On Thu, Aug 11, 2022 at 10:40 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Zhihong Yu <zyu@yugabyte.com> writes:
> In cash_out(), we have the following code:
>     if (value < 0)
>     {
>         /* make the amount positive for digit-reconstruction loop */
>         value = -value;

> The negation cannot be represented in type long when the value is LONG_MIN.

Possibly not good, but it seems like the subsequent loop works anyway:

regression=# select '-92233720368547758.08'::money;
            money           
-----------------------------
 -$92,233,720,368,547,758.08
(1 row)

Note that this exact test case appears in money.sql, so we know that
it works everywhere, not only my machine.

> It seems we can error out when LONG_MIN is detected instead of continuing
> with computation.

How could you think that that's an acceptable solution?  Once the
value is stored, we'd better be able to print it.

                        regards, tom lane

Thanks for taking a look.
I raise this thread due to the following assertion :

src/backend/utils/adt/cash.c:356:11: runtime error: negation of -9223372036854775808 cannot be represented in type 'Cash' (aka 'long'); cast to an unsigned type to negate this value to itself

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../../../../../../src/postgres/src/backend/utils/adt/cash.c:356:11


Though '-92233720368547758.085'::money displays correct error message in other builds, this statement wouldn't pass the build where UndefinedBehaviorSanitizer is active.
I think we should fix this otherwise when there is new assertion triggered due to future changes around Cash (or other types covered by money.sql), we wouldn't see it.

I am open to other ways of bypassing the above assertion.

Cheers

Here is sample output with patch:

# SELECT '-92233720368547758.085'::money;
ERROR:  value "-92233720368547758.085" is out of range for type money
LINE 1: SELECT '-92233720368547758.085'::money; 

FYI

pgsql-hackers by date:

Previous
From: Zhihong Yu
Date:
Subject: Re: avoid negating LONG_MIN in cash_out()
Next
From: Robert Haas
Date:
Subject: Re: [Proposal] Fully WAL logged CREATE DATABASE - No Checkpoints