[PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-02-26 Thread Martin Sebor

The false positive in PR89350 is due to -Wstringop-overflow
trusting that the sizetype offset in POINTER_PLUS_EXPR means
the offset is, in fact, unsigned.  Avoiding the false positive
in the cases when this isn't so is trivial but comes at a cost
of false negatives.  Avoiding those will, I expect, require
enhancing the compute_builtin_object_size() function and that
seems risky at this stage so I would like to defer that until
stage 1.  Except in the instance of memset, the false positives
also aren't too serious because the same problem is also
diagnosed by the -Warray-bounds warning in the wrestrict pass.
Unfortunately, the wrestrict pass only handles copy functions
and not memset.

With that as background, the attached patch avoids
the -Wstringop-overflow false positive by disabling the warning
for offsets whose lower bound is positive and upper bound negative.
To avoid the false negatives for memset the patch lets the wrestrict
pass handle the function (for the bounds checking only).  While
testing this I noticed that the wrestrict pass makes the same
assumption about offsets, so it too is susceptible to similar
false positives.  The rest of the patch corrects this problem
n the wrestrict pass.  Because the pass doesn't depend on
the compute_builtin_object_size() function as much as
-Wstringop-overflow, the fix does not cause false positives (at
least none that I came across).

Tested on x86_64-linux.

Martin
PR tree-optimization/89350 - Wrong -Wstringop-overflow= warning since r261518

gcc/ChangeLog:

	PR tree-optimization/89350
	* builtins.c (compute_objsize): Also ignore offsets whose upper
	bound is negative.
	* gimple-ssa-warn-restrict.c (builtin_memref): Add new member.
	(builtin_memref::builtin_memref): Initialize new member.
	Allow EXPR to be null.
	(builtin_memref::extend_offset_range): Replace local with a member.
	Avoid assuming pointer offsets are unsigned.
	(builtin_memref::set_base_and_offset): Determine base object
	before computing offset range.
	(builtin_access::builtin_access): Handle memset.
	(builtin_access::generic_overlap): Replace local with a member.
	(builtin_access::strcat_overlap): Same.
	(builtin_access::overlap): Same.
	(maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.
	(wrestrict_dom_walker::check_call): Handle memset.
	(check_bounds_or_overlap): Same.

gcc/testsuite/ChangeLog:

	PR tree-optimization/89350
	* gcc.dg/Wstringop-overflow.c: Xfail overly ambitious tests.
	* gcc.dg/Wstringop-overflow-10.c: New test.
	* gcc.dg/Wstringop-overflow-11.c: New test.
	* gcc.dg/pr40340-1.c: Adjust expected warning.
	* gcc.dg/pr40340-2.c: Same.
	* gcc.dg/pr40340-4.c: Same.
	* gcc.dg/pr40340-5.c: Same.

Index: gcc/builtins.c
===
--- gcc/builtins.c	(revision 269190)
+++ gcc/builtins.c	(working copy)
@@ -3652,7 +3652,8 @@ compute_objsize (tree dest, int ostype)
 		  /* Ignore negative offsets for now.  For others,
 			 use the lower bound as the most optimistic
 			 estimate of the (remaining)size.  */
-		  if (wi::sign_mask (min))
+		  if (wi::sign_mask (min)
+			  || wi::sign_mask (max))
 			;
 		  else if (wi::ltu_p (min, wisiz))
 			return wide_int_to_tree (TREE_TYPE (size),
Index: gcc/gimple-ssa-warn-restrict.c
===
--- gcc/gimple-ssa-warn-restrict.c	(revision 269190)
+++ gcc/gimple-ssa-warn-restrict.c	(working copy)
@@ -147,6 +147,9 @@ struct builtin_memref
   /* The size range of the access to this reference.  */
   offset_int sizrange[2];
 
+  /* Cached result of get_max_objsize().  */
+  const offset_int maxobjsize;
+
   /* True for "bounded" string functions like strncat, and strncpy
  and their variants that specify either an exact or upper bound
  on the size of the accesses they perform.  For strncat both
@@ -233,6 +236,7 @@ builtin_memref::builtin_memref (tree expr, tree si
   refoff (HOST_WIDE_INT_MIN),
   offrange (),
   sizrange (),
+  maxobjsize (tree_to_shwi (max_object_size ())),
   strbounded_p ()
 {
   /* Unfortunately, wide_int default ctor is a no-op so array members
@@ -240,7 +244,8 @@ builtin_memref::builtin_memref (tree expr, tree si
   offrange[0] = offrange[1] = 0;
   sizrange[0] = sizrange[1] = 0;
 
-  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
+  if (!expr)
+return;
 
   /* Find the BASE object or pointer referenced by EXPR and set
  the offset range OFFRANGE in the process.  */
@@ -292,13 +297,13 @@ builtin_memref::builtin_memref (tree expr, tree si
 }
 }
 
-/* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.  */
+/* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
+   Pointer offsets are represented as unsigned sizetype but must be
+   treated as signed.  */
 
 void
 builtin_memref::extend_offset_range (tree offset)
 {
-  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
-
   if (TREE_CODE (offset) == INTEGER_

Re: [PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-02-26 Thread Martin Sebor

Please disregard the original patch and consider the attached
version instead.

On 2/26/19 5:03 PM, Martin Sebor wrote:

The false positive in PR89350 is due to -Wstringop-overflow
trusting that the sizetype offset in POINTER_PLUS_EXPR means
the offset is, in fact, unsigned.  Avoiding the false positive
in the cases when this isn't so is trivial but comes at a cost
of false negatives.  Avoiding those will, I expect, require
enhancing the compute_builtin_object_size() function and that
seems risky at this stage so I would like to defer that until
stage 1.  Except in the instance of memset, the false positives
also aren't too serious because the same problem is also
diagnosed by the -Warray-bounds warning in the wrestrict pass.
Unfortunately, the wrestrict pass only handles copy functions
and not memset.

With that as background, the attached patch avoids
the -Wstringop-overflow false positive by disabling the warning
for offsets whose lower bound is positive and upper bound negative.
To avoid the false negatives for memset the patch lets the wrestrict
pass handle the function (for the bounds checking only).  While
testing this I noticed that the wrestrict pass makes the same
assumption about offsets, so it too is susceptible to similar
false positives.  The rest of the patch corrects this problem
n the wrestrict pass.  Because the pass doesn't depend on
the compute_builtin_object_size() function as much as
-Wstringop-overflow, the fix does not cause false positives (at
least none that I came across).

Tested on x86_64-linux.

Martin


PR tree-optimization/89350 - Wrong -Wstringop-overflow= warning since r261518

gcc/ChangeLog:

	PR tree-optimization/89350
	* builtins.c (compute_objsize): Also ignore offsets whose upper
	bound is negative.
	* gimple-ssa-warn-restrict.c (builtin_memref): Add new member.
	(builtin_memref::builtin_memref): Initialize new member.
	Allow EXPR to be null.
	(builtin_memref::extend_offset_range): Replace local with a member.
	Avoid assuming pointer offsets are unsigned.
	(builtin_memref::set_base_and_offset): Determine base object
	before computing offset range.
	(builtin_access::builtin_access): Handle memset.
	(builtin_access::generic_overlap): Replace local with a member.
	(builtin_access::strcat_overlap): Same.
	(builtin_access::overlap): Same.
	(maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.
	(wrestrict_dom_walker::check_call): Handle memset.
	(check_bounds_or_overlap): Same.

gcc/testsuite/ChangeLog:

	PR tree-optimization/89350
	* gcc.dg/Wstringop-overflow.c: Xfail overly ambitious tests.
	* gcc.dg/Wstringop-overflow-10.c: New test.
	* gcc.dg/Wstringop-overflow-11.c: New test.
	* gcc.dg/pr89350.c: New test.
	* gcc.dg/pr40340-1.c: Adjust expected warning.
	* gcc.dg/pr40340-2.c: Same.
	* gcc.dg/pr40340-4.c: Same.
	* gcc.dg/pr40340-5.c: Same.

Index: gcc/builtins.c
===
--- gcc/builtins.c	(revision 269190)
+++ gcc/builtins.c	(working copy)
@@ -3652,7 +3652,8 @@ compute_objsize (tree dest, int ostype)
 		  /* Ignore negative offsets for now.  For others,
 			 use the lower bound as the most optimistic
 			 estimate of the (remaining)size.  */
-		  if (wi::sign_mask (min))
+		  if (wi::sign_mask (min)
+			  || wi::sign_mask (max))
 			;
 		  else if (wi::ltu_p (min, wisiz))
 			return wide_int_to_tree (TREE_TYPE (size),
Index: gcc/gimple-ssa-warn-restrict.c
===
--- gcc/gimple-ssa-warn-restrict.c	(revision 269190)
+++ gcc/gimple-ssa-warn-restrict.c	(working copy)
@@ -147,6 +147,9 @@ struct builtin_memref
   /* The size range of the access to this reference.  */
   offset_int sizrange[2];
 
+  /* Cached result of get_max_objsize().  */
+  const offset_int maxobjsize;
+
   /* True for "bounded" string functions like strncat, and strncpy
  and their variants that specify either an exact or upper bound
  on the size of the accesses they perform.  For strncat both
@@ -233,6 +236,7 @@ builtin_memref::builtin_memref (tree expr, tree si
   refoff (HOST_WIDE_INT_MIN),
   offrange (),
   sizrange (),
+  maxobjsize (tree_to_shwi (max_object_size ())),
   strbounded_p ()
 {
   /* Unfortunately, wide_int default ctor is a no-op so array members
@@ -240,7 +244,8 @@ builtin_memref::builtin_memref (tree expr, tree si
   offrange[0] = offrange[1] = 0;
   sizrange[0] = sizrange[1] = 0;
 
-  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
+  if (!expr)
+return;
 
   /* Find the BASE object or pointer referenced by EXPR and set
  the offset range OFFRANGE in the process.  */
@@ -292,13 +297,13 @@ builtin_memref::builtin_memref (tree expr, tree si
 }
 }
 
-/* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.  */
+/* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
+   Pointer offsets are represented as unsigned sizetype but must be
+   treated as signed.  */
 
 void
 builti

PING [PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-03-06 Thread Martin Sebor

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

(This is marked as a P1 regression.)

On 2/26/19 6:32 PM, Martin Sebor wrote:

Please disregard the original patch and consider the attached
version instead.

On 2/26/19 5:03 PM, Martin Sebor wrote:

The false positive in PR89350 is due to -Wstringop-overflow
trusting that the sizetype offset in POINTER_PLUS_EXPR means
the offset is, in fact, unsigned.  Avoiding the false positive
in the cases when this isn't so is trivial but comes at a cost
of false negatives.  Avoiding those will, I expect, require
enhancing the compute_builtin_object_size() function and that
seems risky at this stage so I would like to defer that until
stage 1.  Except in the instance of memset, the false positives
also aren't too serious because the same problem is also
diagnosed by the -Warray-bounds warning in the wrestrict pass.
Unfortunately, the wrestrict pass only handles copy functions
and not memset.

With that as background, the attached patch avoids
the -Wstringop-overflow false positive by disabling the warning
for offsets whose lower bound is positive and upper bound negative.
To avoid the false negatives for memset the patch lets the wrestrict
pass handle the function (for the bounds checking only).  While
testing this I noticed that the wrestrict pass makes the same
assumption about offsets, so it too is susceptible to similar
false positives.  The rest of the patch corrects this problem
n the wrestrict pass.  Because the pass doesn't depend on
the compute_builtin_object_size() function as much as
-Wstringop-overflow, the fix does not cause false positives (at
least none that I came across).

Tested on x86_64-linux.

Martin






Re: [PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-03-20 Thread Jeff Law
On 2/26/19 6:32 PM, Martin Sebor wrote:
> Please disregard the original patch and consider the attached
> version instead.
> 
> On 2/26/19 5:03 PM, Martin Sebor wrote:
>> The false positive in PR89350 is due to -Wstringop-overflow
>> trusting that the sizetype offset in POINTER_PLUS_EXPR means
>> the offset is, in fact, unsigned.  Avoiding the false positive
>> in the cases when this isn't so is trivial but comes at a cost
>> of false negatives.  Avoiding those will, I expect, require
>> enhancing the compute_builtin_object_size() function and that
>> seems risky at this stage so I would like to defer that until
>> stage 1.  Except in the instance of memset, the false positives
>> also aren't too serious because the same problem is also
>> diagnosed by the -Warray-bounds warning in the wrestrict pass.
>> Unfortunately, the wrestrict pass only handles copy functions
>> and not memset.
>>
>> With that as background, the attached patch avoids
>> the -Wstringop-overflow false positive by disabling the warning
>> for offsets whose lower bound is positive and upper bound negative.
>> To avoid the false negatives for memset the patch lets the wrestrict
>> pass handle the function (for the bounds checking only).  While
>> testing this I noticed that the wrestrict pass makes the same
>> assumption about offsets, so it too is susceptible to similar
>> false positives.  The rest of the patch corrects this problem
>> n the wrestrict pass.  Because the pass doesn't depend on
>> the compute_builtin_object_size() function as much as
>> -Wstringop-overflow, the fix does not cause false positives (at
>> least none that I came across).
>>
>> Tested on x86_64-linux.
>>
>> Martin
> 
> 
> gcc-89350.diff
> 
> PR tree-optimization/89350 - Wrong -Wstringop-overflow= warning since r261518
> 
> gcc/ChangeLog:
> 
>   PR tree-optimization/89350
>   * builtins.c (compute_objsize): Also ignore offsets whose upper
>   bound is negative.
>   * gimple-ssa-warn-restrict.c (builtin_memref): Add new member.
>   (builtin_memref::builtin_memref): Initialize new member.
>   Allow EXPR to be null.
>   (builtin_memref::extend_offset_range): Replace local with a member.
>   Avoid assuming pointer offsets are unsigned.
>   (builtin_memref::set_base_and_offset): Determine base object
>   before computing offset range.
>   (builtin_access::builtin_access): Handle memset.
>   (builtin_access::generic_overlap): Replace local with a member.
>   (builtin_access::strcat_overlap): Same.
>   (builtin_access::overlap): Same.
>   (maybe_diag_overlap): Same.
>   (maybe_diag_access_bounds): Same.
>   (wrestrict_dom_walker::check_call): Handle memset.
>   (check_bounds_or_overlap): Same.
> 
> gcc/testsuite/ChangeLog:
> 
>   PR tree-optimization/89350
>   * gcc.dg/Wstringop-overflow.c: Xfail overly ambitious tests.
>   * gcc.dg/Wstringop-overflow-10.c: New test.
>   * gcc.dg/Wstringop-overflow-11.c: New test.
>   * gcc.dg/pr89350.c: New test.
>   * gcc.dg/pr40340-1.c: Adjust expected warning.
>   * gcc.dg/pr40340-2.c: Same.
>   * gcc.dg/pr40340-4.c: Same.
>   * gcc.dg/pr40340-5.c: Same.
OK.  And just to be clear, totally agree with not trying to change
c_b_o_s to return a range at this point in the release cycle.

jeff


PING #2 [PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-03-11 Thread Martin Sebor

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

On 3/6/19 2:40 PM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

(This is marked as a P1 regression.)

On 2/26/19 6:32 PM, Martin Sebor wrote:

Please disregard the original patch and consider the attached
version instead.

On 2/26/19 5:03 PM, Martin Sebor wrote:

The false positive in PR89350 is due to -Wstringop-overflow
trusting that the sizetype offset in POINTER_PLUS_EXPR means
the offset is, in fact, unsigned.  Avoiding the false positive
in the cases when this isn't so is trivial but comes at a cost
of false negatives.  Avoiding those will, I expect, require
enhancing the compute_builtin_object_size() function and that
seems risky at this stage so I would like to defer that until
stage 1.  Except in the instance of memset, the false positives
also aren't too serious because the same problem is also
diagnosed by the -Warray-bounds warning in the wrestrict pass.
Unfortunately, the wrestrict pass only handles copy functions
and not memset.

With that as background, the attached patch avoids
the -Wstringop-overflow false positive by disabling the warning
for offsets whose lower bound is positive and upper bound negative.
To avoid the false negatives for memset the patch lets the wrestrict
pass handle the function (for the bounds checking only).  While
testing this I noticed that the wrestrict pass makes the same
assumption about offsets, so it too is susceptible to similar
false positives.  The rest of the patch corrects this problem
n the wrestrict pass.  Because the pass doesn't depend on
the compute_builtin_object_size() function as much as
-Wstringop-overflow, the fix does not cause false positives (at
least none that I came across).

Tested on x86_64-linux.

Martin








PING #3 [PATCH] correct handling of offsets in bounds warnings (PR 89350)

2019-03-18 Thread Martin Sebor

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

As an aside, I introduced the same mistake/false positive in
three places: -Wstringop-overflow in builtins.c, -Warray-bounds
in gimple-ssa-warn-restrict.c, and -Warray-bounds in tree-vrp.c.
This patch fixes the first two.  I'm working on PR 89720 to fix
the last one.

On 3/11/19 8:52 PM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

On 3/6/19 2:40 PM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-02/msg02029.html

(This is marked as a P1 regression.)

On 2/26/19 6:32 PM, Martin Sebor wrote:

Please disregard the original patch and consider the attached
version instead.

On 2/26/19 5:03 PM, Martin Sebor wrote:

The false positive in PR89350 is due to -Wstringop-overflow
trusting that the sizetype offset in POINTER_PLUS_EXPR means
the offset is, in fact, unsigned.  Avoiding the false positive
in the cases when this isn't so is trivial but comes at a cost
of false negatives.  Avoiding those will, I expect, require
enhancing the compute_builtin_object_size() function and that
seems risky at this stage so I would like to defer that until
stage 1.  Except in the instance of memset, the false positives
also aren't too serious because the same problem is also
diagnosed by the -Warray-bounds warning in the wrestrict pass.
Unfortunately, the wrestrict pass only handles copy functions
and not memset.

With that as background, the attached patch avoids
the -Wstringop-overflow false positive by disabling the warning
for offsets whose lower bound is positive and upper bound negative.
To avoid the false negatives for memset the patch lets the wrestrict
pass handle the function (for the bounds checking only).  While
testing this I noticed that the wrestrict pass makes the same
assumption about offsets, so it too is susceptible to similar
false positives.  The rest of the patch corrects this problem
n the wrestrict pass.  Because the pass doesn't depend on
the compute_builtin_object_size() function as much as
-Wstringop-overflow, the fix does not cause false positives (at
least none that I came across).

Tested on x86_64-linux.

Martin