Re: [HACKERS] [PATCH] avoid buffer underflow in errfinish()

2013-03-27 Thread Xi Wang
On Wed, Mar 27, 2013 at 9:03 AM, Heikki Linnakangas
 wrote:
> Writing it like that suggests that autovac might sometimes be NULL, even if
> deadlock_state == DS_BLOCKED_BY_AUTOVACUUM. From your explanation above, I
> gather that's not possible (and I think you're right), so the NULL check is
> unnecessary. If we think it might be NULL after all, the above makes sense.

That makes sense.  Thanks for the clarification!

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH] avoid buffer underflow in errfinish()

2013-03-23 Thread Xi Wang
A side question: at src/backend/storage/lmgr/proc.c:1150, is there a
null pointer deference for `autovac'?

There is a null pointer check `autovac != NULL', but the pointer is
already dereferenced earlier when initializing `autovac_pgxact'.  Is
this null pointer check redundant, or should we move the dereference
`autovac->pgprocno' after the check?  Thanks.

On Sat, Mar 23, 2013 at 6:38 PM, Xi Wang  wrote:
> CHECK_STACK_DEPTH checks if errordata_stack_depth is negative.
> Move the dereference of &errordata[errordata_stack_depth] after
> the check to avoid out-of-bounds read.
> ---
>  src/backend/utils/error/elog.c |4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
> index 3a211bf..47a0a8b 100644
> --- a/src/backend/utils/error/elog.c
> +++ b/src/backend/utils/error/elog.c
> @@ -393,13 +393,15 @@ void
>  errfinish(int dummy,...)
>  {
> ErrorData  *edata = &errordata[errordata_stack_depth];
> -   int elevel = edata->elevel;
> +   int elevel;
> MemoryContext oldcontext;
> ErrorContextCallback *econtext;
>
> recursion_depth++;
> CHECK_STACK_DEPTH();
>
> +   elevel = edata->elevel;
> +
> /*
>  * Do processing in ErrorContext, which we hope has enough reserved 
> space
>  * to report an error.
> --
> 1.7.10.4
>


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH] avoid buffer underflow in errfinish()

2013-03-23 Thread Xi Wang
CHECK_STACK_DEPTH checks if errordata_stack_depth is negative.
Move the dereference of &errordata[errordata_stack_depth] after
the check to avoid out-of-bounds read.
---
 src/backend/utils/error/elog.c |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 3a211bf..47a0a8b 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -393,13 +393,15 @@ void
 errfinish(int dummy,...)
 {
ErrorData  *edata = &errordata[errordata_stack_depth];
-   int elevel = edata->elevel;
+   int elevel;
MemoryContext oldcontext;
ErrorContextCallback *econtext;
 
recursion_depth++;
CHECK_STACK_DEPTH();
 
+   elevel = edata->elevel;
+
/*
 * Do processing in ErrorContext, which we hope has enough reserved 
space
 * to report an error.
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH 0/3] Work around icc miscompilation

2013-02-23 Thread Xi Wang
It depends on the context.  In the patches, `a' is known to be
non-negative, so `INT_MAX - a' cannot overflow.  If you ignore the
context and talk about the general case, then it can.

- xi

On Sat, Feb 23, 2013 at 12:25 PM, Tom Lane  wrote:
> Greg Stark  writes:
>> He's changing things to do
>
>> if (INT_MAX - a > b)
>>   PG_THROW ("a+b would overflow")
>> else
>>   x=a+b;
>
>> Why would a smarter compiler be licensed to conclude that it can
>> optimize away anything? "INT_MAX-a > b" is always well defined.
>
> Really?  Can't "INT_MAX - a" overflow?
>
> regards, tom lane


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH 0/3] Work around icc miscompilation

2013-01-24 Thread Xi Wang
On 1/24/13 10:48 AM, Tom Lane wrote:
> The fundamental problem here is that the compiler, unless told otherwise
> by a compilation switch, believes it is entitled to assume that no
> integer overflow will happen anywhere in the program.  Therefore, any
> error check that is looking for overflow *should* get optimized away.
> The only reason the compiler would fail to do that is if its optimizer
> isn't quite smart enough to prove that the code is testing for an
> overflow condition.  So what you are proposing here is merely the next
> move in an arms race with the compiler writers, and it will surely
> break again in a future generation of compilers.  Or even if these
> particular trouble spots don't break, something else will.  The only
> reliable solution is to not let the compiler make that type of
> assumption.

What I am proposing here is the opposite: _not_ to enter an arm race
with the compiler writers.  Instead, make the code conform to the C
standard, something both sides can agree on.

Particularly, avoid using (signed) overflowed results to detect
overflows, which the C standard clearly specifies as undefined
behavior and many compilers are actively exploiting.

We could use either unsigned overflows (which is well defined) or
precondition testing (like `x > INT_MAX - y' in the patches).

> So I think we should just reject all of these, and instead fix configure
> to make sure it turns on icc's equivalent of -fwrapv.

While I agree it's better to turn on icc's -fno-strict-overflow as a
workaround, the fundamental problem here is that we are _not_
programming in the C language.  Rather, we are programming in some
C-with-signed-wrapraround dialect.

The worst part of this C dialect is that it has never been specified
clearly what it means by "signed wraparound":

gcc's -fwrapv assumes signed wraparound for add/sub/mul, but not for
div (e.g., INT_MIN/-1 traps on x86) nor shift (e.g., 1<<32 produces
undef with clang).

clang's -fwrapv also assumes workaround for pointer arithmetic, while
gcc's does not.

I have no idea what icc and pathscale's -fno-strict-overflow option
does (probably the closest thing to -fwrapv).  Sometimes it prevents
such checks from being optimized away, sometimes it doesn't.

Anyway, it would not be surprising if future C compilers break this
dialect again.  But they shouldn't break standard-conforming code.

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH 0/3] Work around icc miscompilation

2013-01-24 Thread Xi Wang
On 1/24/13 5:02 AM, Heikki Linnakangas wrote:
> These patches look ok at a quick glance, but how do we ensure this kind 
> of problems don't crop back again in the future? Does icc give a warning 
> about these? Do we have a buildfarm animal that produces the warnings?
> 
> If we fix these, can we stop using -frapv on gcc? Is there any way to 
> get gcc to warn about these?

Thanks for reviewing.

gcc has this -Wstrict-overflow option to warn against overflow checks
that may be optimized away.  The result in inaccurate: it may produce
a large number of false warnings, and it may also miss many cases (esp.
when gcc's value-range-propagation fails to compute variables' ranges).

Not sure if other compilers have similar options.

I find these broken checks using a static checker I'm developing, and
only report cases that existing compilers do miscompile.  If you are
interested, I'll post a complete list of overflow checks in pgsql that
invoke undefined behavior and thus may be killed by future compilers.

I believe we can get rid of -fwrapv once we fix all such checks.

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 3/3] Fix overflow checking in repeat()

2013-01-24 Thread Xi Wang
icc optimizes away `check + VARHDRSZ <= check' since signed integer
overflow is undefined behavior.  Simplify the overflow check for
`VARHDRSZ + count * slen' as `count > (INT_MAX - VARHDRSZ) / slen'.
---
 src/backend/utils/adt/oracle_compat.c |   18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/src/backend/utils/adt/oracle_compat.c 
b/src/backend/utils/adt/oracle_compat.c
index d448088..a85a672 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -15,6 +15,8 @@
  */
 #include "postgres.h"
 
+#include 
+
 #include "utils/builtins.h"
 #include "utils/formatting.h"
 #include "mb/pg_wchar.h"
@@ -1034,20 +1036,14 @@ repeat(PG_FUNCTION_ARGS)
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 (slen != 0 && count > (INT_MAX - VARHDRSZ) / slen)
+   ereport(ERROR,
+   (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+errmsg("requested length too large")));
 
+   tlen = VARHDRSZ + (count * slen);
result = (text *) palloc(tlen);
 
SET_VARSIZE(result, tlen);
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 2/3] Fix x + 1 < x overflow checks

2013-01-24 Thread Xi Wang
icc optimizes away x + 1 < x because signed integer overflow is
undefined behavior in C.  Instead, simply check if x is INT_MAX.
---
 src/backend/utils/adt/float.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index b73e0d5..344b092 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -2764,12 +2764,12 @@ width_bucket_float8(PG_FUNCTION_ARGS)
result = 0;
else if (operand >= bound2)
{
-   result = count + 1;
/* check for overflow */
-   if (result < count)
+   if (count == INT_MAX)
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;
@@ -2780,12 +2780,12 @@ width_bucket_float8(PG_FUNCTION_ARGS)
result = 0;
else if (operand <= bound2)
{
-   result = count + 1;
/* check for overflow */
-   if (result < count)
+   if (count == INT_MAX)
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;
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 1/3] Fix x + y < x overflow checks

2013-01-24 Thread Xi Wang
icc optimizes away the overflow check x + y < x (y > 0), because
signed integer overflow is undefined behavior in C.  Instead, use
a safe precondition test x > INT_MAX - y.
---
 src/backend/utils/adt/varbit.c  |7 +--
 src/backend/utils/adt/varlena.c |   10 ++
 src/pl/plpgsql/src/pl_exec.c|4 ++--
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 1712c12..af69200 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -16,6 +16,8 @@
 
 #include "postgres.h"
 
+#include 
+
 #include "access/htup_details.h"
 #include "libpq/pqformat.h"
 #include "nodes/nodeFuncs.h"
@@ -1138,12 +1140,13 @@ 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)
+   if (sl > INT_MAX - sp)
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);
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 95e41bf..c907f44 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -997,12 +997,13 @@ 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)
+   if (sl > INT_MAX - sp)
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);
@@ -2020,12 +2021,13 @@ 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)
+   if (sl > INT_MAX - sp)
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);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 0ecf651..a9cf6df 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1972,13 +1972,13 @@ exec_stmt_fori(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_fori *stmt)
 */
if (stmt->reverse)
{
-   if ((int32) (loop_value - step_value) > loop_value)
+   if (loop_value < INT_MIN + step_value)
break;
loop_value -= step_value;
}
else
{
-   if ((int32) (loop_value + step_value) < loop_value)
+   if (loop_value > INT_MAX - step_value)
break;
loop_value += step_value;
}
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 0/3] Work around icc miscompilation

2013-01-24 Thread Xi Wang
I'm sending three smaller patches for review, which try to fix icc
and pathscale (mis)compilation problems described in my last email.

Not sure if we need to fix the overflow check x + 1 <= 0 (x > 0) at
src/backend/executor/execQual.c:3088, which icc optimizes away, too.

  Fix x + y < x overflow checks
  Fix x + 1 < x overflow checks
  Fix overflow checking in repeat()

 src/backend/utils/adt/float.c |8 
 src/backend/utils/adt/oracle_compat.c |   18 +++---
 src/backend/utils/adt/varbit.c|7 +--
 src/backend/utils/adt/varlena.c   |   10 ++
 src/pl/plpgsql/src/pl_exec.c  |4 ++--
 5 files changed, 24 insertions(+), 23 deletions(-)

On 1/20/13 2:58 AM, Xi Wang wrote:
> Intel's icc and PathScale's pathcc compilers optimize away several
> overflow checks, since they consider signed integer overflow as
> undefined behavior.  This leads to a vulnerable binary.
> 
> Currently we use -fwrapv to disable such (mis)optimizations in gcc,
> but not in other compilers.
> 
> 
> Examples
> 
> 
> 1) x + 1 <= 0 (assuming x > 0).
> 
> src/backend/executor/execQual.c:3088
> 
> Below is the simplified code.
> 
> -
> void bar(void);
> void foo(int this_ndims)
> {
>  if (this_ndims <= 0)
>  return;
>  int elem_ndims = this_ndims;
>  int ndims = elem_ndims + 1;
>  if (ndims <= 0)
>  bar();
> }
> -
> 
> $ icc -S -o - sadd1.c
> ...
> foo:
> # parameter 1: %edi
> ..B1.1:
> ..___tag_value_foo.1:
> ..B1.2:
>  ret
> 
> 2) x + 1 < x
> 
> src/backend/utils/adt/float.c:2769
> src/backend/utils/adt/float.c:2785
> src/backend/utils/adt/oracle_compat.c:1045 (x + C < x)
> 
> Below is the simplified code.
> 
> -
> void bar(void);
> void foo(int count)
> {
>  int result = count + 1;
>  if (result < count)
>  bar();
> }
> -
> 
> $ icc -S -o - sadd2.c
> ...
> foo:
> # parameter 1: %edi
> ..B1.1:
> ..___tag_value_foo.1:
>  ret
> 3) x + y <= x (assuming y > 0)
> 
> src/backend/utils/adt/varbit.c:1142
> src/backend/utils/adt/varlena.c:1001
> src/backend/utils/adt/varlena.c:2024
> src/pl/plpgsql/src/pl_exec.c:1975
> src/pl/plpgsql/src/pl_exec.c:1981
> 
> Below is the simplified code.
> 
> -
> void bar(void);
> void foo(int sp, int sl)
> {
>  if (sp <= 0)
>  return;
>  int sp_pl_sl = sp + sl;
>  if (sp_pl_sl <= sl)
>  bar();
> }
> -
> 
> $ icc -S -o - sadd3.c
> foo:
> # parameter 1: %edi
> # parameter 2: %esi
> ..B1.1:
> ..___tag_value_foo.1:
> ..B1.2:
>  ret
> 
> Possible fixes
> ==
> 
> * Recent versions of icc and pathcc support gcc's workaround option,
> -fno-strict-overflow, to disable some optimizations based on signed
> integer overflow.  It's better to add this option to configure.
> They don't support gcc's -fwrapv yet.
> 
> * This -fno-strict-overflow option cannot help in all cases: it cannot
> prevent the latest icc from (mis)compiling the 1st case.  We could also
> fix the source code by avoiding signed integer overflows, as follows.
> 
> x + y <= 0 (assuming x > 0, y > 0)
> --> x > INT_MAX - y
> 
> x + y <= x (assuming y > 0)
> --> x > INT_MAX - y
> 
> I'd suggest to fix the code rather than trying to work around the
> compilers since the fix seems simple and portable.
> 
> See two recent compiler bugs of -fwrapv/-fno-strict-overflow as well.
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55883
> http://software.intel.com/en-us/forums/topic/358200
> 
> * I don't have access to IBM's xlc compiler.  Not sure how it works for
> the above cases.
> 
> - xi
> 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [RFC] overflow checks optimized away

2013-01-22 Thread Xi Wang
Intel's icc and PathScale's pathcc compilers optimize away several
overflow checks, since they consider signed integer overflow as
undefined behavior.  This leads to a vulnerable binary.

Currently we use -fwrapv to disable such (mis)optimizations in gcc,
but not in other compilers.


Examples


1) x + 1 <= 0 (assuming x > 0).

src/backend/executor/execQual.c:3088

Below is the simplified code.

-
void bar(void);
void foo(int this_ndims)
{
if (this_ndims <= 0)
return;
int elem_ndims = this_ndims;
int ndims = elem_ndims + 1;
if (ndims <= 0)
bar();
}
-

$ icc -S -o - sadd1.c
...
foo:
# parameter 1: %edi
..B1.1:
..___tag_value_foo.1:
..B1.2:
ret

2) x + 1 < x

src/backend/utils/adt/float.c:2769
src/backend/utils/adt/float.c:2785
src/backend/utils/adt/oracle_compat.c:1045 (x + C < x)

Below is the simplified code.

-
void bar(void);
void foo(int count)
{
int result = count + 1;
if (result < count)
bar();
}
-

$ icc -S -o - sadd2.c
...
foo:
# parameter 1: %edi
..B1.1:
..___tag_value_foo.1:
ret   

3) x + y <= x (assuming y > 0)

src/backend/utils/adt/varbit.c:1142
src/backend/utils/adt/varlena.c:1001
src/backend/utils/adt/varlena.c:2024
src/pl/plpgsql/src/pl_exec.c:1975
src/pl/plpgsql/src/pl_exec.c:1981

Below is the simplified code.

-
void bar(void);
void foo(int sp, int sl)
{
if (sp <= 0)
return;
int sp_pl_sl = sp + sl;
if (sp_pl_sl <= sl)
bar();
}
-

$ icc -S -o - sadd3.c
foo:
# parameter 1: %edi
# parameter 2: %esi
..B1.1:
..___tag_value_foo.1:
..B1.2:
ret   


Possible fixes
==

* Recent versions of icc and pathcc support gcc's workaround option,
-fno-strict-overflow, to disable some optimizations based on signed
integer overflow.  It's better to add this option to configure.
They don't support gcc's -fwrapv yet.

* This -fno-strict-overflow option cannot help in all cases: it cannot
prevent the latest icc from (mis)compiling the 1st case.  We could also
fix the source code by avoiding signed integer overflows, as follows.

x + y <= 0 (assuming x > 0, y > 0)
--> x > INT_MAX - y

x + y <= x (assuming y > 0)
--> x > INT_MAX - y

I'd suggest to fix the code rather than trying to work around the
compilers since the fix seems simple and portable.

See two recent compiler bugs of -fwrapv/-fno-strict-overflow as well.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55883
http://software.intel.com/en-us/forums/topic/358200

* I don't have access to IBM's xlc compiler.  Not sure how it works for
the above cases.

- xi 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH] Fix NULL checking in check_TSCurrentConfig()

2013-01-21 Thread Xi Wang

On 1/20/13 10:35 PM, Tom Lane wrote:

Great catch, will commit.  (But first I'm looking through commit
2594cf0e to see if I made the same mistake anywhere else :-(.)

How did you find that, coverity or some such tool?


Thanks for reviewing the patch.

It was found using a homemade static undefined behavior checker.

- xi


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [RFC] overflow checks optimized away

2013-01-19 Thread Xi Wang
Intel's icc and PathScale's pathcc compilers optimize away several
overflow checks, since they consider signed integer overflow as
undefined behavior.  This leads to a vulnerable binary.

Currently we use -fwrapv to disable such (mis)optimizations in gcc,
but not in other compilers.


Examples


1) x + 1 <= 0 (assuming x > 0).

src/backend/executor/execQual.c:3088

Below is the simplified code.

-
void bar(void);
void foo(int this_ndims)
{
if (this_ndims <= 0)
return;
int elem_ndims = this_ndims;
int ndims = elem_ndims + 1;
if (ndims <= 0)
bar();
}
-

$ icc -S -o - sadd1.c
...
foo:
# parameter 1: %edi
..B1.1:
..___tag_value_foo.1:
..B1.2:
ret

2) x + 1 < x

src/backend/utils/adt/float.c:2769
src/backend/utils/adt/float.c:2785
src/backend/utils/adt/oracle_compat.c:1045 (x + C < x)

Below is the simplified code.

-
void bar(void);
void foo(int count)
{
int result = count + 1;
if (result < count)
bar();
}
-

$ icc -S -o - sadd2.c
...
foo:
# parameter 1: %edi
..B1.1:
..___tag_value_foo.1:
ret   
3) x + y <= x (assuming y > 0)

src/backend/utils/adt/varbit.c:1142
src/backend/utils/adt/varlena.c:1001
src/backend/utils/adt/varlena.c:2024
src/pl/plpgsql/src/pl_exec.c:1975
src/pl/plpgsql/src/pl_exec.c:1981

Below is the simplified code.

-
void bar(void);
void foo(int sp, int sl)
{
if (sp <= 0)
return;
int sp_pl_sl = sp + sl;
if (sp_pl_sl <= sl)
bar();
}
-

$ icc -S -o - sadd3.c
foo:
# parameter 1: %edi
# parameter 2: %esi
..B1.1:
..___tag_value_foo.1:
..B1.2:
ret   

Possible fixes
==

* Recent versions of icc and pathcc support gcc's workaround option,
-fno-strict-overflow, to disable some optimizations based on signed
integer overflow.  It's better to add this option to configure.
They don't support gcc's -fwrapv yet.

* This -fno-strict-overflow option cannot help in all cases: it cannot
prevent the latest icc from (mis)compiling the 1st case.  We could also
fix the source code by avoiding signed integer overflows, as follows.

x + y <= 0 (assuming x > 0, y > 0)
--> x > INT_MAX - y

x + y <= x (assuming y > 0)
--> x > INT_MAX - y

I'd suggest to fix the code rather than trying to work around the
compilers since the fix seems simple and portable.

See two recent compiler bugs of -fwrapv/-fno-strict-overflow as well.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55883
http://software.intel.com/en-us/forums/topic/358200

* I don't have access to IBM's xlc compiler.  Not sure how it works for
the above cases.

- xi 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH] Fix off-by-one in PQprintTuples()

2013-01-19 Thread Xi Wang
Don't write past the end of tborder; the size is width + 1.
---
 src/interfaces/libpq/fe-print.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
index 076e1cc..7ed489a 100644
--- a/src/interfaces/libpq/fe-print.c
+++ b/src/interfaces/libpq/fe-print.c
@@ -706,7 +706,7 @@ PQprintTuples(const PGresult *res,
fprintf(stderr, libpq_gettext("out of 
memory\n"));
abort();
}
-   for (i = 0; i <= width; i++)
+   for (i = 0; i < width; i++)
tborder[i] = '-';
tborder[i] = '\0';
fprintf(fout, "%s\n", tborder);
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH] Fix NULL checking in check_TSCurrentConfig()

2013-01-19 Thread Xi Wang
The correct NULL check should use `*newval'; `newval' must be non-null.
---
 src/backend/utils/cache/ts_cache.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/utils/cache/ts_cache.c 
b/src/backend/utils/cache/ts_cache.c
index e688b1a..65a8ad7 100644
--- a/src/backend/utils/cache/ts_cache.c
+++ b/src/backend/utils/cache/ts_cache.c
@@ -642,7 +642,7 @@ check_TSCurrentConfig(char **newval, void **extra, 
GucSource source)
free(*newval);
*newval = strdup(buf);
pfree(buf);
-   if (!newval)
+   if (!*newval)
return false;
}
 
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [RFC] Fix div/mul crash and more undefined behavior

2012-11-19 Thread Xi Wang
On 11/19/12 11:04 AM, Tom Lane wrote:
> I thought about this some more and realized that we can handle it
> by realizing that division by -1 is the same as negation, and so
> we can copy the method used in int4um.  So the code would look like
> 
>   if (arg2 == -1)
>   {
>   result = -arg1;
>   if (arg1 != 0 && SAMESIGN(result, arg1))
>   ereport(ERROR, ...);
>   PG_RETURN_INT32(result);
>   }
> 
> (with rather more comments than this, of course).  This looks faster
> than what's there now, as well as removing the need for use of
> explicit INT_MIN constants.

Hah, I used exactly the same code in my initial patch. :)

See below.

> They'd better not, else they'll break many of our overflow checks.
> This is why we use -fwrapv with gcc, for example.  Any other compiler
> with similar optimizations needs to be invoked with a similar switch.

Yes, that's the scary part.

Even with -fwrapv in gcc (I tried 4.6/4.7/4.8), it still optimizes away
my overflow check!

if (arg1 < 0 && -arg1 < 0) { ... }

Fortunately, it doesn't optimize way checks using SAMESIGN() for now.
Who knows what could happen in the next version..

Clang's -fwrapv works as expected.

PathScale and Open64 (and probably icc) don't support -fwrapv at all.
Not sure if they have similar options.  They do such optimizations, too.

The reality is that C compilers are not friendly to postcondition
checking; they consider signed integer overflow as undefined behavior,
so they do whatever they want to do.  Even workaround options like
-fwrapv are often broken, not to mention that they may not even have
those options.

That's why I am suggesting to avoid postcondition checking for signed
integer overflow.

> Not every C compiler provides stdint.h, unfortunately --- otherwise
> I'd not be so resistant to depending on this.

Sigh..  You are right.

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [RFC] Fix div/mul crash and more undefined behavior

2012-11-18 Thread Xi Wang
On 11/18/12 6:47 PM, Tom Lane wrote:
> Xi Wang  writes:
>> [ patch adding a bunch of explicit INT_MIN/MAX constants ]
> 
> I was against this style of coding before, and I still am.
> For one thing, it's just about certain to introduce conflicts
> against system headers.

I totally agree.

I would be happy to rewrite the integer overflow checks without
using these explicit constants, but it seems extremely tricky to
do so.  One possible check without using INTn_MIN is:

if (arg1 < 0 && -arg1 < 0 && arg2 == -1) { ... }

Compared to (arg1 == INTn_MIN && arg2 == -1), the above check is
not only more confusing and difficult to understand, but it also
invokes undefined behavior (-INT_MIN overflow), which is dangerous:
many C compilers will optimize away the check.  I've tried gcc,
clang, PathScale, and AMD's Open64, all of which perform such
optimizations.

Since INTn_MIN and INTn_MAX are standard macros from the C library,
can we assume that every C compiler should provide them in stdint.h?
At least this is true for gcc, clang, and Visual C++.  Then we don't
have to define them and worry about possible conflicts (though I
think using #ifndef...#endif should be able to avoid conflicts).

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [RFC] Fix div/mul crash and more undefined behavior

2012-11-18 Thread Xi Wang
The INT_MIN / -1 crash problem was partially addressed in 2006 and
commit 9fc6f4e1ae107f44807c4906105e1f7eb052ecb1.

http://archives.postgresql.org/pgsql-patches/2006-06/msg00102.php

However, the fix is incomplete and incorrect for some cases.

64-bit crash


Below is an example that crashes PostgreSQL on Windows, using the
64-bit binary from http://www.postgresql.org/download/windows/.

SELECT ((-9223372036854775808)::int8) % (-1);

Note that the previous discussion concluded that int8 (64-bit)
division didn't crash, which is incorrect.

http://archives.postgresql.org/pgsql-patches/2006-06/msg00104.php

My guess is that the previous test was carried out on a 32-bit
Windows, where there's no 64-bit division instruction.  In that
case, the generated code calls a runtime function (e.g., lldiv),
which doesn't trap.  However, on a 64-bit system, the compiler
generates the idivq instruction, which leads to a crash.

Note that the problem is not limited to division.  The following
multiplication crashes as well:

SELECT ((-9223372036854775808)::int8) * ((-1)::int8);

The reason is that the multiplication overflow check uses a division.

32-bit crash


The previous fix doesn't fix all possible crashes, even on a 32-bit
Windows.  Below is an example to crash a 32-bit PostgreSQL:

SELECT ((-2147483648)::int4) % ((-1)::int2);

Portability
===

The previous fix uses #ifdef WIN32 ... #endif, which is not portable,
as noted below:

http://archives.postgresql.org/pgsql-patches/2006-06/msg00103.php

Using a SIGFPE handler is also dangerous (e.g., causing an infinite
loop sometimes):

https://www.securecoding.cert.org/confluence/display/seccode/SIG35-C.+Do+not+return+from+SIGSEGV,+SIGILL,+or+SIGFPE+signal+handlers

Strictly speaking, using postcondition checking to detect signed
division overflows (actually, all signed integer overflows) violates
the C language standard, because signed integer overflow is undefined
behavior in C and we cannot first compute the result and then check
for overflow.  Compilers can do a lot of funny and crazy things
(e.g., generating traps or even optimizing away overflow checks).

BTW, PostgreSQL currently uses gcc's workaround option -fwrapv to
disable offending optimizations based on integer overflows.  The
problems are: (1) it doesn't always work (e.g., for division), and
(2) many other C compilers do not even support this workaround
option and can perform offending optimizations.

Patching


Below is a patch that fixes division crashes.  It removes #ifdef WIN32
and tries to use portable checks.  I'll send more (e.g., for fixing
multiplication crashes) if this looks good.

I understand that the existing integer overflow checks tried to
avoid dependency on constants like INT64_MIN.  But I'm not sure how
to perform simpler and portable overflow checks without using such
constants.

Also, I could use the SHRT_MIN rather than introducing INT16_MIN; I just
feel like using INT16_MIN with int16 is clearer and less confusing.

diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 9f752ed..d7867cb 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -732,30 +732,18 @@ int4div(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
 
-#ifdef WIN32
-
/*
-* Win32 doesn't throw a catchable exception for SELECT -2147483648 /
-* (-1); -- INT_MIN
+* Overflow check.  The only possible overflow case is for arg1 =
+* INT32_MIN, arg2 = -1, where the correct result is -INT32_MIN, which
+* can't be represented on a two's-complement machine.
 */
-   if (arg2 == -1 && arg1 == INT_MIN)
+   if (arg1 == INT32_MIN && arg2 == -1)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 errmsg("integer out of range")));
-#endif
 
result = arg1 / arg2;
 
-   /*
-* Overflow check.  The only possible overflow case is for arg1 = 
INT_MIN,
-* arg2 = -1, where the correct result is -INT_MIN, which can't be
-* represented on a two's-complement machine.  Most machines produce
-* INT_MIN but it seems some produce zero.
-*/
-   if (arg2 == -1 && arg1 < 0 && result <= 0)
-   ereport(ERROR,
-   (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-errmsg("integer out of range")));
PG_RETURN_INT32(result);
 }
 
@@ -877,18 +865,17 @@ int2div(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
 
-   result = arg1 / arg2;
-
-   /*
-* Overflow check.  The only possible overflow case is for arg1 =
-* SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN, which 
can't
-* be represented on a two's-complement machine.  Most machines produce
-* SHRT_MIN but it seems some produce zero.

Re: [HACKERS] [PATCH] Fix INT_MIN % -1 overflow in int8mod().

2012-11-14 Thread Xi Wang
On 11/14/12 5:03 PM, Tom Lane wrote:
> No need, I'm already patching it.

Oops.  Sorry.  Ignore my patches.

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 2/2] Clean up INT_MIN % -1 overflow in int4mod().

2012-11-14 Thread Xi Wang
Since x % -1 returns 0 for any x, we don't need the check x == INT_MIN.

Suggested by Tom Lane.
---
 src/backend/utils/adt/int.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 4be3901..3e423fe 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -1096,7 +1096,7 @@ int4mod(PG_FUNCTION_ARGS)
}
 
/* SELECT ((-2147483648)::int4) % (-1); causes a floating point 
exception */
-   if (arg1 == INT_MIN && arg2 == -1)
+   if (arg2 == -1)
PG_RETURN_INT32(0);
 
/* No overflow is possible */
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH 1/2] Fix INT_MIN % -1 overflow in int8mod().

2012-11-14 Thread Xi Wang
Return 0 for x % -1 instead of throwing an exception (e.g., when x
is INT_MIN).

Suggested by Tom Lane.
---
 src/backend/utils/adt/int8.c |4 
 1 file changed, 4 insertions(+)

diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 0e59956..a30ab36 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -649,6 +649,10 @@ int8mod(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
 
+   /* SELECT ((-9223372036854775808)::int8) % (-1); causes a floating 
point exception */
+   if (arg2 == -1)
+   PG_RETURN_INT64(0);
+
/* No overflow is possible */
 
PG_RETURN_INT64(arg1 % arg2);
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] [PATCH] Fix INT_MIN % -1 overflow in int8mod().

2012-11-14 Thread Xi Wang
On 11/14/12 4:46 PM, Tom Lane wrote:
> Meh.  I didn't care for the explicit dependency on INT_MIN in the
> previous patch, and I like introducing INT64_MIN even less.  I think
> we should be able to reduce the test to just
> 
>   if (arg2 == -1)
>   return 0;
> 
> since zero is the correct result for any value of arg1, not only
> INT_MIN.

I agree.  Will send a v2.  Thanks. :)

- xi


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] [PATCH] Fix INT_MIN % -1 overflow in int8mod().

2012-11-14 Thread Xi Wang
Return 0 for INT_MIN % -1 (64-bit) instead of throwing an exception.
This patch complements commit f9ac414c that fixed int4mod().
---
 src/backend/utils/adt/int8.c |4 
 src/include/c.h  |7 +++
 2 files changed, 11 insertions(+)

diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 0e59956..9da651b 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -649,6 +649,10 @@ int8mod(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
 
+   /* SELECT ((-9223372036854775808)::int8) % (-1); causes a floating 
point exception */
+   if (arg1 == INT64_MIN && arg2 == -1)
+   PG_RETURN_INT64(0);
+
/* No overflow is possible */
 
PG_RETURN_INT64(arg1 % arg2);
diff --git a/src/include/c.h b/src/include/c.h
index a6c0e6e..d20ba8c 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -294,6 +294,13 @@ typedef unsigned long long int uint64;
 #define UINT64CONST(x) ((uint64) x)
 #endif
 
+#ifndef INT64_MAX
+#define INT64_MAX INT64CONST(9223372036854775807)
+#endif
+
+#ifndef INT64_MIN
+#define INT64_MIN (-INT64_MAX-1)
+#endif
 
 /* Select timestamp representation (float8 or int64) */
 #ifdef USE_INTEGER_DATETIMES
-- 
1.7.10.4



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers