Thread: pgsql: Provide overflow safe integer math inline functions.

pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:
Provide overflow safe integer math inline functions.

It's not easy to get signed integer overflow checks correct and
fast. Therefore abstract the necessary infrastructure into a common
header providing addition, subtraction and multiplication for 16, 32,
64 bit signed integers.

The new macros aren't yet used, but a followup commit will convert
several open coded overflow checks.

Author: Andres Freund, with some code stolen from Greg Stark
Reviewed-By: Robert Haas
Discussion: https://postgr.es/m/20171024103954.ztmatprlglz3rwke@alap3.anarazel.de

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/4d6ad31257adaf8a51e1c4377d96afa656d9165f

Modified Files
--------------
config/c-compiler.m4          |  22 ++++
configure                     |  33 ++++++
configure.in                  |   4 +
src/include/common/int.h      | 239 ++++++++++++++++++++++++++++++++++++++++++
src/include/pg_config.h.in    |   3 +
src/include/pg_config.h.win32 |   3 +
6 files changed, 304 insertions(+)


Re: pgsql: Provide overflow safe integer math inline functions.

From
Christoph Berg
Date:
Re: Andres Freund 2017-12-13 <E1eOvQF-00075r-Cy@gemulon.postgresql.org>
> Provide overflow safe integer math inline functions.

The new _overflow functions have buggy comments:

/*
 * If a - b overflows, return true, otherwise store the result of a + b into
 * *result.                                                         ^ there

Christoph


Re: pgsql: Provide overflow safe integer math inline functions.

From
Robert Haas
Date:
On Wed, Dec 13, 2017 at 5:10 AM, Christoph Berg <myon@debian.org> wrote:
> Re: Andres Freund 2017-12-13 <E1eOvQF-00075r-Cy@gemulon.postgresql.org>
>> Provide overflow safe integer math inline functions.
>
> The new _overflow functions have buggy comments:
>
> /*
>  * If a - b overflows, return true, otherwise store the result of a + b into
>  * *result.                                                         ^ there

What's wrong with that?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:
On 2017-12-13 09:37:25 -0500, Robert Haas wrote:
> On Wed, Dec 13, 2017 at 5:10 AM, Christoph Berg <myon@debian.org> wrote:
> > Re: Andres Freund 2017-12-13 <E1eOvQF-00075r-Cy@gemulon.postgresql.org>
> >> Provide overflow safe integer math inline functions.
> >
> > The new _overflow functions have buggy comments:
> >
> > /*
> >  * If a - b overflows, return true, otherwise store the result of a + b into
> >  * *result.                                                         ^ there
> 
> What's wrong with that?

After staring at it for a while, I seem to have partially mis-copied the
note for addition to the subtraction operation...

Greetings,

Andres Freund


Re: pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:
Hi Michael,

On 2017-12-13 01:01:19 +0000, Andres Freund wrote:
> Provide overflow safe integer math inline functions.

https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=dangomushi&dt=2017-12-13%2018%3A00%3A18

which seems half like a compiler bug to me. But either way, we gotta
work around it.  I suspect the reason configure test doesn't
sufficiently detect this here is because it's testing the function with
constant arguments.

Could you perhaps test whether replacing PGAC_C_BUILTIN_OP_OVERFLOW's body with something like
result
PG_INT64_TYPE a;
PG_INT64_TYPE b;
PG_INT64_TYPE result;
__builtin_mul_overflow(*(volatile PG_INT64_TYPE*) &a, *(volatile PG_INT64_TYPE*) &b, &result);

makes it fail? I'd rather not test this via the buildfarm, given that
dangomushi isn't the most frequently running / fastest animal.

- Andres


Re: pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:
On 2017-12-13 13:37:54 -0800, Andres Freund wrote:
> Hi Michael,
> 
> On 2017-12-13 01:01:19 +0000, Andres Freund wrote:
> > Provide overflow safe integer math inline functions.
> 
> https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=dangomushi&dt=2017-12-13%2018%3A00%3A18
> 
> which seems half like a compiler bug to me. But either way, we gotta
> work around it.  I suspect the reason configure test doesn't
> sufficiently detect this here is because it's testing the function with
> constant arguments.
> 
> Could you perhaps test whether replacing PGAC_C_BUILTIN_OP_OVERFLOW's body with something like
> result
> PG_INT64_TYPE a;
> PG_INT64_TYPE b;
> PG_INT64_TYPE result;
> __builtin_mul_overflow(*(volatile PG_INT64_TYPE*) &a, *(volatile PG_INT64_TYPE*) &b, &result);
> 
> makes it fail? I'd rather not test this via the buildfarm, given that
> dangomushi isn't the most frequently running / fastest animal.

I've since tried this via the buildfarm, but still:

configure:14480: checking for __builtin_mul_overflow
configure:14500: ccache clang -o conftest -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement
-Wendif-labels-Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv
-Wno-unused-command-line-argument-g -O2  -D_GNU_SOURCE  -I/usr/include/et   conftest.c -lssl -lcrypto -lz -lreadline
-lrt-lcrypt -ldl -lm  >&5
 
configure:14500: $? = 0
configure:14508: result: yes

I'm not quite following. Could you check if the same happens without
-O2? Not because that'd be a solution, but to narrow down how this
happens?

Greetings,

Andres Freund


Re: pgsql: Provide overflow safe integer math inline functions.

From
Tom Lane
Date:
Andres Freund <andres@anarazel.de> writes:
> I'm not quite following. Could you check if the same happens without
> -O2? Not because that'd be a solution, but to narrow down how this
> happens?

The committed test looks quite broken to me: it's missing some &
operators.  Not sure how that translates into failing to fail the
configure test, but personally I'd have done this like

volatile PG_INT64_TYPE a = 1;
volatile PG_INT64_TYPE b = 1;
PG_INT64_TYPE result;
__builtin_mul_overflow(a, b, &result);

            regards, tom lane


Re: pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:

On December 16, 2017 5:31:01 PM PST, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>Andres Freund <andres@anarazel.de> writes:
>> I'm not quite following. Could you check if the same happens without
>> -O2? Not because that'd be a solution, but to narrow down how this
>> happens?
>
>The committed test looks quite broken to me: it's missing some &
>operators.  Not sure how that translates into failing to fail the
>configure test,

Hm, true. As you say, it doesn't explain the problem though, it's just weird int  to ptr cases. Kinda seems like clang
linksto a different runtime during the configure tests than what's used for postgres... 

Andres

Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.


Re: pgsql: Provide overflow safe integer math inline functions.

From
Tom Lane
Date:
Andres Freund <andres@anarazel.de> writes:
> On December 16, 2017 5:31:01 PM PST, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> The committed test looks quite broken to me: it's missing some &
>> operators.  Not sure how that translates into failing to fail the
>> configure test,

> Hm, true. As you say, it doesn't explain the problem though, it's just weird int  to ptr cases. Kinda seems like
clanglinks to a different runtime during the configure tests than what's used for postgres... 

What I'm thinking is that that somehow prevents the "volatile" from
having any effect.  On my laptop (recent Apple clang), the function call
certainly does seem to get optimized away with the test-as-committed...

Oh!  It seems to get optimized away with my "volatile" version too.

I think the real issue, or part of it, is that you need to assign the
result to a global variable, not a local one, so that the compiler
doesn't decide it can forget the whole thing.  And maybe store the
bool result somewhere, too.

Marking the result and bool-result variables as volatile might
be an OK substitute for making them global.  But the global way
is what we've done in older configure test programs.

            regards, tom lane


Re: pgsql: Provide overflow safe integer math inline functions.

From
Michael Paquier
Date:
On Sun, Dec 17, 2017 at 9:32 AM, Andres Freund <andres@anarazel.de> wrote:
> I've since tried this via the buildfarm, but still:
>
> configure:14480: checking for __builtin_mul_overflow
> configure:14500: ccache clang -o conftest -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement
-Wendif-labels-Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv
-Wno-unused-command-line-argument-g -O2  -D_GNU_SOURCE  -I/usr/include/et   conftest.c -lssl -lcrypto -lz -lreadline
-lrt-lcrypt -ldl -lm  >&5 
> configure:14500: $? = 0
> configure:14508: result: yes
>
> I'm not quite following. Could you check if the same happens without
> -O2? Not because that'd be a solution, but to narrow down how this
> happens?

I have triggered a new test manually this morning on dangomushi
because I knew that it would fail as I have tested as well stuff
similar to the version you have pushed. Please note that if you added
a volatile cast to "result" as well, then compilation was able to
complete and regression tests passed...
--
Michael


Re: pgsql: Provide overflow safe integer math inline functions.

From
Tom Lane
Date:
Michael Paquier <michael.paquier@gmail.com> writes:
> ... Please note that if you added
> a volatile cast to "result" as well, then compilation was able to
> complete and regression tests passed...

Yeah, that squares with my analysis: the problem with the existing test
is that the compiler is throwing away the function call because its
output is unused.

If I haven't seen something from Andres shortly, I'll push a fix.

            regards, tom lane


Re: pgsql: Provide overflow safe integer math inline functions.

From
Michael Paquier
Date:
On Mon, Dec 18, 2017 at 1:03 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Michael Paquier <michael.paquier@gmail.com> writes:
>> ... Please note that if you added
>> a volatile cast to "result" as well, then compilation was able to
>> complete and regression tests passed...
>
> Yeah, that squares with my analysis: the problem with the existing test
> is that the compiler is throwing away the function call because its
> output is unused.
>
> If I haven't seen something from Andres shortly, I'll push a fix.

And the buildfarm is happy again. Thanks for the fix.
-- 
Michael


Re: pgsql: Provide overflow safe integer math inline functions.

From
Andres Freund
Date:
On 2017-12-17 11:03:49 -0500, Tom Lane wrote:
> Michael Paquier <michael.paquier@gmail.com> writes:
> > ... Please note that if you added
> > a volatile cast to "result" as well, then compilation was able to
> > complete and regression tests passed...
> 
> Yeah, that squares with my analysis: the problem with the existing test
> is that the compiler is throwing away the function call because its
> output is unused.
> 
> If I haven't seen something from Andres shortly, I'll push a fix.

Thanks! Was off for most of yesterday...

Greetings,

Andres Freund