public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] use pointer size rather than array size when storing the former (PR 93829)
@ 2020-02-20  0:27 Martin Sebor
  2020-02-20  7:04 ` Bernhard Reutner-Fischer
  2020-02-26 22:09 ` Jeff Law
  0 siblings, 2 replies; 5+ messages in thread
From: Martin Sebor @ 2020-02-20  0:27 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

The buffer overflow detection for multi-char stores uses the size
of a source array even when what's actually being accessed (read
and stored) is a pointer to the array.  That leads to incorrect
warnings in some cases.

The attached patch corrects the function that computes the size of
the access to set it to that of a pointer instead if the source is
an address expression.

Tested on x86_64-linux.

Martin

[-- Attachment #2: gcc-93829.diff --]
[-- Type: text/x-patch, Size: 4036 bytes --]

PR middle-end/93829 - bogus -Wstringop-overflow on memcpy of a struct with a pointer member from another with a long string

gcc/testsuite/ChangeLog:

	PR middle-end/93829
	* gcc.dg/Wstringop-overflow-32.c: New test.

gcc/ChangeLog:

	PR middle-end/93829
	* tree-ssa-strlen.c (count_nonzero_bytes): Set the size to that
	  of a pointer in the outermost ADDR_EXPRs.

diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 9a88a85b07c..1cdb581a51f 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -4587,12 +4587,15 @@ int ssa_name_limit_t::next_ssa_name (tree ssa_name)
 
 /* Determines the minimum and maximum number of leading non-zero bytes
    in the representation of EXP and set LENRANGE[0] and LENRANGE[1]
-   to each.  Sets LENRANGE[2] to the total number of bytes in
-   the representation.  Sets *NULTREM if the representation contains
-   a zero byte, and sets *ALLNUL if all the bytes are zero.
+   to each.
+   Sets LENRANGE[2] to the total size of the access (which may be less
+   than LENRANGE[1] when what's being referenced by EXP is a pointer
+   rather than an array).
+   Sets *NULTREM if the representation contains a zero byte, and sets
+   *ALLNUL if all the bytes are zero.
    OFFSET and NBYTES are the offset into the representation and
-   the size of the access to it determined from a MEM_REF or zero
-   for other expressions.
+   the size of the access to it determined from an ADDR_EXPR (i.e.,
+   a pointer) or MEM_REF or zero for other expressions.
    Uses RVALS to determine range information.
    Avoids recursing deeper than the limits in SNLIM allow.
    Returns true on success and false otherwise.  */
@@ -4692,7 +4695,13 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
     }
 
   if (TREE_CODE (exp) == ADDR_EXPR)
-    exp = TREE_OPERAND (exp, 0);
+    {
+      /* If the size of the access hasn't been determined yet it's that
+	 of a pointer.  */
+      if (!nbytes)
+	nbytes = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+      exp = TREE_OPERAND (exp, 0);
+    }
 
   if (TREE_CODE (exp) == SSA_NAME)
     {
@@ -4788,9 +4797,10 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
 	return false;
 
       if (!nbytes)
-	/* If NBYTES hasn't been determined earlier from MEM_REF,
-	   set it here.  It includes all internal nuls, including
-	   the terminating one if the string has one.  */
+	/* If NBYTES hasn't been determined earlier, either from ADDR_EXPR
+	   (i.e., it's the size of a pointer), or from MEM_REF (as the size
+	   of the access), set it here to the size of the string, including
+	   all internal and trailing nuls if the string has any.  */
 	nbytes = nchars - offset;
 
       prep = TREE_STRING_POINTER (exp) + offset;
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-32.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-32.c
new file mode 100644
index 00000000000..e5939567a4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-32.c
@@ -0,0 +1,51 @@
+/* PR middle-end/93829 - bogus -Wstringop-overflow on memcpy of a struct
+   with a pointer member from another with a long string
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+extern void* memcpy (void*, const void*, __SIZE_TYPE__);
+
+#define S40 "0123456789012345678901234567890123456789"
+
+const char s40[] = S40;
+
+struct S
+{
+  const void *p, *q, *r;
+} s, sa[2];
+
+
+void test_lit_decl (void)
+{
+  struct S t = { 0, S40, 0 };
+
+  memcpy (&s, &t, sizeof t);    // { dg-bogus "-Wstringop-overflow" }
+}
+
+void test_str_decl (void)
+{
+  struct S t = { 0, s40, 0 };
+
+  memcpy (&s, &t, sizeof t);    // { dg-bogus "-Wstringop-overflow" }
+}
+
+
+void test_lit_ssa (int i)
+{
+  if (i < 1)
+    i = 1;
+  struct S *p = &sa[i];
+  struct S t = { 0, S40, 0 };
+
+  memcpy (p, &t, sizeof t);    // { dg-bogus "-Wstringop-overflow" }
+}
+
+void test_str_ssa (int i)
+{
+  if (i < 1)
+    i = 1;
+  struct S *p = &sa[i];
+  struct S t = { 0, s40, 0 };
+
+  memcpy (p, &t, sizeof t);    // { dg-bogus "-Wstringop-overflow" }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-02-28 21:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-20  0:27 [PATCH] use pointer size rather than array size when storing the former (PR 93829) Martin Sebor
2020-02-20  7:04 ` Bernhard Reutner-Fischer
2020-02-26 22:09 ` Jeff Law
2020-02-26 23:18   ` Martin Sebor
2020-02-28 21:11     ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).