[committed,4/7] analyzer: more bounds-checking wording tweaks [PR106626]

Message ID 20221201024200.3722982-4-dmalcolm@redhat.com
State Committed
Commit df460cf51b25868564dd2628a399b8c874ef309c
Headers
Series [committed,1/7] analyzer: move bounds checking to a new bounds-checking.cc |

Commit Message

David Malcolm Dec. 1, 2022, 2:41 a.m. UTC
  This patch tweaks the wording of -Wanalyzer-out-of-bounds:

* use the spellings/terminology of CWE:
  * replace "underread" with "under-read", as per:
     https://cwe.mitre.org/data/definitions/127.html
  * replace "overread" with "over-read" as per:
     https://cwe.mitre.org/data/definitions/126.html
  * replace "underflow" with "underwrite" as per:
    https://cwe.mitre.org/data/definitions/124.html

* wherever known, specify the memory region of the bad access,
so that it says e.g. "heap-based buffer over-read"
or "stack-based buffer over-read"

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r13-4428-gdf460cf51b2586.

gcc/analyzer/ChangeLog:
	PR analyzer/106626
	* bounds-checking.cc (out_of_bounds::get_memory_space): New.
	(buffer_overflow::emit): Use it.
	(class buffer_overread): Rename to...
	(class buffer_over_read): ...this.
	(buffer_over_read::emit): Specify which memory space the read is
	from, where known.  Change "overread" to "over-read".
	(class buffer_underflow): Rename to...
	(class buffer_underwrite): ...this.
	(buffer_underwrite::emit): Specify which memory space the write is
	to, where known.  Change "underflow" to "underwrite".
	(class buffer_underread): Rename to...
	(class buffer_under_read): Rename to...
	(buffer_under_read::emit): Specify which memory space the read is
	from, where known.  Change "underread" to "under-read".
	(symbolic_past_the_end::get_memory_space): New.
	(symbolic_buffer_overflow::emit): Use it.
	(class symbolic_buffer_overread): Rename to...
	(class symbolic_buffer_over_read): ...this.
	(symbolic_buffer_over_read::emit): Specify which memory space the
	read is from, where known.  Change "overread" to "over-read".
	(region_model::check_symbolic_bounds): Update for class renaming.
	(region_model::check_region_bounds): Likewise.

gcc/testsuite/ChangeLog:
	PR analyzer/106626
	* gcc.dg/analyzer/call-summaries-2.c: Update expected results.
	* gcc.dg/analyzer/out-of-bounds-1.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-2.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-3.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-4.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-5.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-container_of.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-read-char-arr.c: Likewise.  Rename
	functions from "int_arr_" to "char_arr_".
	* gcc.dg/analyzer/out-of-bounds-read-int-arr.c: Update expected
	results.
	* gcc.dg/analyzer/out-of-bounds-read-struct-arr.c: New test.
	* gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Update expected
	results.  Rename functions from "int_arr_" to "char_arr_".
	* gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Update expected
	results.
	* gcc.dg/analyzer/out-of-bounds-write-struct-arr.c: New test.
	* gcc.dg/analyzer/pr101962.c: Update expected results.
	* gcc.dg/analyzer/realloc-5.c: Update expected results.
	* gcc.dg/analyzer/zlib-3.c: Update expected results.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/bounds-checking.cc               | 133 +++++++++++++-----
 .../gcc.dg/analyzer/call-summaries-2.c        |   2 +-
 .../gcc.dg/analyzer/out-of-bounds-1.c         |   4 +-
 .../gcc.dg/analyzer/out-of-bounds-2.c         |  15 +-
 .../gcc.dg/analyzer/out-of-bounds-3.c         |  27 ++--
 .../gcc.dg/analyzer/out-of-bounds-4.c         |  15 +-
 .../gcc.dg/analyzer/out-of-bounds-5.c         |  20 +--
 .../analyzer/out-of-bounds-container_of.c     |   4 +-
 .../analyzer/out-of-bounds-read-char-arr.c    |  34 +++--
 .../analyzer/out-of-bounds-read-int-arr.c     |  18 ++-
 .../analyzer/out-of-bounds-read-struct-arr.c  |  65 +++++++++
 .../analyzer/out-of-bounds-write-char-arr.c   |  22 +--
 .../analyzer/out-of-bounds-write-int-arr.c    |   6 +-
 .../analyzer/out-of-bounds-write-struct-arr.c |  65 +++++++++
 gcc/testsuite/gcc.dg/analyzer/pr101962.c      |   2 +-
 gcc/testsuite/gcc.dg/analyzer/realloc-5.c     |   2 +-
 gcc/testsuite/gcc.dg/analyzer/zlib-3.c        |   2 +-
 17 files changed, 327 insertions(+), 109 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-struct-arr.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-struct-arr.c
  

Patch

diff --git a/gcc/analyzer/bounds-checking.cc b/gcc/analyzer/bounds-checking.cc
index b02bc79a926..bc7d2dd17ae 100644
--- a/gcc/analyzer/bounds-checking.cc
+++ b/gcc/analyzer/bounds-checking.cc
@@ -71,6 +71,11 @@  public:
   }
 
 protected:
+  enum memory_space get_memory_space () const
+  {
+    return m_reg->get_memory_space ();
+  }
+
   /* Potentially add a note about valid ways to index this array, such
      as (given "int arr[10];"):
        note: valid subscripts for 'arr' are '[0]' to '[9]'
@@ -150,7 +155,7 @@  public:
   {
     diagnostic_metadata m;
     bool warned;
-    switch (m_reg->get_memory_space ())
+    switch (get_memory_space ())
       {
       default:
 	m.add_cwe (787);
@@ -234,22 +239,36 @@  public:
   }
 };
 
-/* Concrete subclass to complain about buffer overreads.  */
+/* Concrete subclass to complain about buffer over-reads.  */
 
-class buffer_overread : public past_the_end
+class buffer_over_read : public past_the_end
 {
 public:
-  buffer_overread (const region *reg, tree diag_arg,
-		   byte_range range, tree byte_bound)
+  buffer_over_read (const region *reg, tree diag_arg,
+		    byte_range range, tree byte_bound)
   : past_the_end (reg, diag_arg, range, byte_bound)
   {}
 
   bool emit (rich_location *rich_loc) final override
   {
     diagnostic_metadata m;
+    bool warned;
     m.add_cwe (126);
-    bool warned = warning_meta (rich_loc, m, get_controlling_option (),
-				"buffer overread");
+    switch (get_memory_space ())
+      {
+      default:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "buffer over-read");
+	break;
+      case MEMSPACE_STACK:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "stack-based buffer over-read");
+	break;
+      case MEMSPACE_HEAP:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "heap-based buffer over-read");
+	break;
+      }
 
     if (warned)
       {
@@ -316,21 +335,35 @@  public:
   }
 };
 
-/* Concrete subclass to complain about buffer underflows.  */
+/* Concrete subclass to complain about buffer underwrites.  */
 
-class buffer_underflow : public out_of_bounds
+class buffer_underwrite : public out_of_bounds
 {
 public:
-  buffer_underflow (const region *reg, tree diag_arg, byte_range range)
+  buffer_underwrite (const region *reg, tree diag_arg, byte_range range)
   : out_of_bounds (reg, diag_arg, range)
   {}
 
   bool emit (rich_location *rich_loc) final override
   {
     diagnostic_metadata m;
+    bool warned;
     m.add_cwe (124);
-    bool warned = warning_meta (rich_loc, m, get_controlling_option (),
-				"buffer underflow");
+    switch (get_memory_space ())
+      {
+      default:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "buffer underwrite");
+	break;
+      case MEMSPACE_STACK:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "stack-based buffer underwrite");
+	break;
+      case MEMSPACE_HEAP:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "heap-based buffer underwrite");
+	break;
+      }
     if (warned)
       maybe_describe_array_bounds (rich_loc->get_loc ());
     return warned;
@@ -368,21 +401,35 @@  public:
   }
 };
 
-/* Concrete subclass to complain about buffer underreads.  */
+/* Concrete subclass to complain about buffer under-reads.  */
 
-class buffer_underread : public out_of_bounds
+class buffer_under_read : public out_of_bounds
 {
 public:
-  buffer_underread (const region *reg, tree diag_arg, byte_range range)
+  buffer_under_read (const region *reg, tree diag_arg, byte_range range)
   : out_of_bounds (reg, diag_arg, range)
   {}
 
   bool emit (rich_location *rich_loc) final override
   {
     diagnostic_metadata m;
+    bool warned;
     m.add_cwe (127);
-    bool warned = warning_meta (rich_loc, m, get_controlling_option (),
-				"buffer underread");
+    switch (get_memory_space ())
+      {
+      default:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "buffer under-read");
+	break;
+      case MEMSPACE_STACK:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "stack-based buffer under-read");
+	break;
+      case MEMSPACE_HEAP:
+	warned = warning_meta (rich_loc, m, get_controlling_option (),
+			       "heap-based buffer under-read");
+	break;
+      }
     if (warned)
       maybe_describe_array_bounds (rich_loc->get_loc ());
     return warned;
@@ -519,6 +566,11 @@  public:
   }
 
 protected:
+  enum memory_space get_memory_space () const
+  {
+    return m_reg->get_memory_space ();
+  }
+
   const region *m_reg;
   tree m_diag_arg;
   tree m_offset;
@@ -542,7 +594,7 @@  public:
   bool emit (rich_location *rich_loc) final override
   {
     diagnostic_metadata m;
-    switch (m_reg->get_memory_space ())
+    switch (get_memory_space ())
       {
       default:
 	m.add_cwe (787);
@@ -560,13 +612,13 @@  public:
   }
 };
 
-/* Concrete subclass to complain about overreads with symbolic values.  */
+/* Concrete subclass to complain about over-reads with symbolic values.  */
 
-class symbolic_buffer_overread : public symbolic_past_the_end
+class symbolic_buffer_over_read : public symbolic_past_the_end
 {
 public:
-  symbolic_buffer_overread (const region *reg, tree diag_arg, tree offset,
-			    tree num_bytes, tree capacity)
+  symbolic_buffer_over_read (const region *reg, tree diag_arg, tree offset,
+			     tree num_bytes, tree capacity)
   : symbolic_past_the_end (reg, diag_arg, offset, num_bytes, capacity)
   {
     m_dir_str = "read";
@@ -576,8 +628,21 @@  public:
   {
     diagnostic_metadata m;
     m.add_cwe (126);
-    return warning_meta (rich_loc, m, get_controlling_option (),
-			 "buffer overread");
+    switch (get_memory_space ())
+      {
+      default:
+	m.add_cwe (787);
+	return warning_meta (rich_loc, m, get_controlling_option (),
+			     "buffer over-read");
+      case MEMSPACE_STACK:
+	m.add_cwe (121);
+	return warning_meta (rich_loc, m, get_controlling_option (),
+			     "stack-based buffer over-read");
+      case MEMSPACE_HEAP:
+	m.add_cwe (122);
+	return warning_meta (rich_loc, m, get_controlling_option (),
+			     "heap-based buffer over-read");
+      }
   }
 };
 
@@ -609,11 +674,11 @@  region_model::check_symbolic_bounds (const region *base_reg,
 	  gcc_unreachable ();
 	  break;
 	case DIR_READ:
-	  ctxt->warn (make_unique<symbolic_buffer_overread> (base_reg,
-							     diag_arg,
-							     offset_tree,
-							     num_bytes_tree,
-							     capacity_tree));
+	  ctxt->warn (make_unique<symbolic_buffer_over_read> (base_reg,
+							      diag_arg,
+							      offset_tree,
+							      num_bytes_tree,
+							      capacity_tree));
 	  break;
 	case DIR_WRITE:
 	  ctxt->warn (make_unique<symbolic_buffer_overflow> (base_reg,
@@ -701,7 +766,7 @@  region_model::check_region_bounds (const region *reg,
   /* NUM_BYTES_TREE should always be interpreted as unsigned.  */
   byte_offset_t num_bytes_unsigned = wi::to_offset (num_bytes_tree);
   byte_range read_bytes (offset, num_bytes_unsigned);
-  /* If read_bytes has a subset < 0, we do have an underflow.  */
+  /* If read_bytes has a subset < 0, we do have an underwrite.  */
   if (read_bytes.falls_short_of_p (0, &out))
     {
       tree diag_arg = get_representative_tree (base_reg);
@@ -711,10 +776,10 @@  region_model::check_region_bounds (const region *reg,
 	  gcc_unreachable ();
 	  break;
 	case DIR_READ:
-	  ctxt->warn (make_unique<buffer_underread> (reg, diag_arg, out));
+	  ctxt->warn (make_unique<buffer_under_read> (reg, diag_arg, out));
 	  break;
 	case DIR_WRITE:
-	  ctxt->warn (make_unique<buffer_underflow> (reg, diag_arg, out));
+	  ctxt->warn (make_unique<buffer_underwrite> (reg, diag_arg, out));
 	  break;
 	}
     }
@@ -739,8 +804,8 @@  region_model::check_region_bounds (const region *reg,
 	  gcc_unreachable ();
 	  break;
 	case DIR_READ:
-	  ctxt->warn (make_unique<buffer_overread> (reg, diag_arg,
-						    out, byte_bound));
+	  ctxt->warn (make_unique<buffer_over_read> (reg, diag_arg,
+						     out, byte_bound));
 	  break;
 	case DIR_WRITE:
 	  ctxt->warn (make_unique<buffer_overflow> (reg, diag_arg,
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
index a7a17dbd358..22ca475b2ed 100644
--- a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
@@ -329,7 +329,7 @@  int test_returns_element_ptr (int j)
   __analyzer_eval (*returns_element_ptr (0) == 7); /* { dg-warning "TRUE" } */
   __analyzer_eval (*returns_element_ptr (1) == 8); /* { dg-warning "TRUE" } */
   __analyzer_eval (*returns_element_ptr (2) == 9); /* { dg-warning "TRUE" } */
-  return *returns_element_ptr (3); /* { dg-warning "buffer overread" } */
+  return *returns_element_ptr (3); /* { dg-warning "buffer over-read" } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[2\\\]'" "valid subscript note" { target *-*-* } .-1 } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c
index dc4de9b28a6..977476ed2fb 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-1.c
@@ -93,7 +93,7 @@  void test6 (void)
 
   /* { dg-warning "buffer overflow" "warning" { target *-*-* } test6b } */
   /* { dg-message "" "note" { target *-*-* } test6b } */
-  /* { dg-warning "buffer overread" "warning" { target *-*-* } test6c } */
+  /* { dg-warning "buffer over-read" "warning" { target *-*-* } test6c } */
   /* { dg-message "" "note" { target *-*-* } test6c } */
 }
 
@@ -116,7 +116,7 @@  void test7 (void)
   fn (destBuf, srcBuf, returnChunkSize (destBuf)); /* { dg-line test7 } */
 
   // TODO: Should we handle widening_svalues as a follow-up?
-  /* { dg-warning "overread" "warning" { xfail *-*-* } test7 } */
+  /* { dg-warning "over-read" "warning" { xfail *-*-* } test7 } */
   /* { dg-warning "overflow" "warning" { xfail *-*-* } test7 } */
   /* { dg-message "" "note" { xfail *-*-* } test7 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c
index 0df9364c5c1..1330090f348 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-2.c
@@ -3,7 +3,7 @@ 
 #include <stdio.h>
 #include <stdint.h>
 
-/* Wanalyzer-out-of-bounds tests for buffer overreads.  */
+/* Wanalyzer-out-of-bounds tests for buffer over-reads.  */
 
 /* Avoid folding of memcpy.  */
 typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
@@ -21,8 +21,9 @@  void test1 (void)
   memset (id_sequence, 0, 3 * sizeof(int));
   printf ("%i", id_sequence[3]); /* { dg-line test1 } */
 
-  /* { dg-warning "overread" "warning" { target *-*-* } test1 } */
-  /* { dg-message "" "note" { target *-*-* } test1 } */
+  /* { dg-warning "stack-based buffer over-read" "warning" { target *-*-* } test1 } */
+  /* { dg-message "read of 4 bytes from after the end of 'id_sequence'" "num bad bytes note" { target *-*-* } test1 } */
+  /* { dg-message "valid subscripts for 'id_sequence' are '\\\[0\\\]' to '\\\[2\\\]'" "valid subscript note" { target *-*-* } test1 } */
 }
 
 void test2 (void)
@@ -46,7 +47,7 @@  void test3 (void)
   for (int i = n; i > 0; i--)
     sum += arr[i]; /* { dg-line test3 } */
 
-  /* { dg-warning "overread" "warning" { target *-*-* } test3 } */
+  /* { dg-warning "stack-based buffer over-read" "warning" { target *-*-* } test3 } */
   /* { dg-message "" "note" { target *-*-* } test3 } */
 }
 
@@ -78,6 +79,8 @@  void test5 (void)
     sum += *(arr + i); /* { dg-line test5 } */
 
   free (arr);
-  /* { dg-warning "overread" "warning" { target *-*-* } test5 } */
-  /* { dg-message "" "note" { target *-*-* } test5 } */
+  /* { dg-warning "heap-based buffer over-read" "bounds warning" { target *-*-* } test5 } */
+  /* { dg-message "read of 4 bytes from after the end of the region" "num bad bytes note" { target *-*-* } test5 } */
+
+  /* { dg-warning "use of uninitialized value" "uninit warning" { target *-*-* } test5 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c
index 7446b182e48..5fd9cc3c6b1 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-3.c
@@ -2,7 +2,7 @@ 
 #include <string.h>
 #include <stdint.h>
 
-/* Wanalyzer-out-of-bounds tests for buffer underreads and writes.  */
+/* Wanalyzer-out-of-bounds tests for buffer under-reads and underwrites.  */
 
 /* Avoid folding of memcpy.  */
 typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
@@ -19,8 +19,9 @@  void test1 (void)
   int *e = buf - 1;
   *e = 42; /* { dg-line test1 } */
 
-  /* { dg-warning "underflow" "warning" { target *-*-* } test1 } */
-  /* { dg-message "" "note" { target *-*-* } test1 } */
+  /* { dg-warning "stack-based buffer underwrite" "warning" { target *-*-* } test1 } */
+  /* { dg-message "out-of-bounds write from byte -4 till byte -1 but 'buf' starts at byte 0" "final event" { target *-*-* } test1 } */
+  /* { dg-message "valid subscripts for 'buf' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test1 } */
 }
 
 void test2 (void)
@@ -38,8 +39,9 @@  void test3 (void)
   *e = 123;
   *(e - 2) = 321; /* { dg-line test3 } */
 
-  /* { dg-warning "underflow" "warning" { target *-*-* } test3 } */
-  /* { dg-message "" "note" { target *-*-* } test3 } */
+  /* { dg-warning "stack-based buffer underwrite" "warning" { target *-*-* } test3 } */
+  /* { dg-message "out-of-bounds write from byte -4 till byte -1 but 'buf' starts at byte 0" "final event" { target *-*-* } test3 } */
+  /* { dg-message "valid subscripts for 'buf' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test3 } */
 }
 
 void test4 (void)
@@ -50,8 +52,9 @@  void test4 (void)
   int n = -4;
   fn (&(buf[n]), buf, sizeof (int));  /* { dg-line test4 } */
 
-  /* { dg-warning "underflow" "warning" { target *-*-* } test4 } */
-  /* { dg-message "" "note" { target *-*-* } test4 } */
+  /* { dg-warning "stack-based buffer underwrite" "warning" { target *-*-* } test4 } */
+  /* { dg-message "out-of-bounds write from byte -16 till byte -13 but 'buf' starts at byte 0" "final event" { target *-*-* } test4 } */
+  /* { dg-message "valid subscripts for 'buf' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test4 } */
 }
 
 void test5 (void)
@@ -63,8 +66,9 @@  void test5 (void)
   for (int i = 4; i >= 0; i++)
     sum += *(buf - i); /* { dg-line test5 } */
 
-  /* { dg-warning "underread" "warning" { target *-*-* } test5 } */
-  /* { dg-message "" "note" { target *-*-* } test5 } */
+  /* { dg-warning "stack-based buffer under-read" "warning" { target *-*-* } test5 } */
+  /* { dg-message "out-of-bounds read from byte -16 till byte -13 but 'buf' starts at byte 0" "final event" { target *-*-* } test5 } */
+  /* { dg-message "valid subscripts for 'buf' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test5 } */
 }
 
 void test6 (void)
@@ -86,6 +90,7 @@  void test8 (void)
   int n = -4;
   fn (buf, &(buf[n]), sizeof (int));  /* { dg-line test8 } */
 
-  /* { dg-warning "underread" "warning" { target *-*-* } test8 } */
-  /* { dg-message "" "note" { target *-*-* } test8 } */
+  /* { dg-warning "stack-based buffer under-read" "warning" { target *-*-* } test8 } */
+  /* { dg-message "out-of-bounds read from byte -16 till byte -13 but 'buf' starts at byte 0" "note" { target *-*-* } test8 } */
+  /* { dg-message "valid subscripts for 'buf' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test8 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-4.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-4.c
index 46f600de658..9cd8bda76c3 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-4.c
@@ -11,8 +11,9 @@  void test1 (void)
   char dst[5];
   strcpy (dst, "Hello"); /* { dg-line test1 } */
 
-  /* { dg-warning "overflow" "warning" { target *-*-* } test1 } */
-  /* { dg-message "dst" "note" { target *-*-* } test1 } */
+  /* { dg-warning "stack-based buffer overflow" "warning" { target *-*-* } test1 } */
+  /* { dg-message "write of 1 byte to beyond the end of 'dst'" "num bad bytes note" { target *-*-* } test1 } */
+  /* { dg-message "valid subscripts for 'dst' are '\\\[0\\\]' to '\\\[4\\\]'" "valid subscript note" { target *-*-* } test1 } */
 }
 
 void test2 (void)
@@ -27,8 +28,9 @@  void test3 (void)
   char dst[5];
   strcpy (dst, src); /* { dg-line test3 } */
 
-  /* { dg-warning "overflow" "warning" { target *-*-* } test3 } */
-  /* { dg-message "dst" "note" { target *-*-* } test3 } */
+  /* { dg-warning "stack-based buffer overflow" "warning" { target *-*-* } test3 } */
+  /* { dg-message "write of 1 byte to beyond the end of 'dst'" "num bad bytes note" { target *-*-* } test3 } */
+  /* { dg-message "valid subscripts for 'dst' are '\\\[0\\\]' to '\\\[4\\\]'" "valid subscript note" { target *-*-* } test3 } */
 }
 
 void test4 (void)
@@ -51,8 +53,9 @@  void test5 (void)
   char dst[5];
   strcpy (dst, str); /* { dg-line test5 } */
 
-  /* { dg-warning "overflow" "warning" { target *-*-* } test5 } */
-  /* { dg-message "dst" "note" { target *-*-* } test5 } */
+  /* { dg-warning "stack-based buffer overflow" "warning" { target *-*-* } test5 } */
+  /* { dg-message "write of 1 byte to beyond the end of 'dst'" "num bad bytes note" { target *-*-* } test5 } */
+  /* { dg-message "valid subscripts for 'dst' are '\\\[0\\\]' to '\\\[4\\\]'" "valid subscript note" { target *-*-* } test5 } */
 }
 
 void test6 (void)
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-5.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-5.c
index 7dc0bc5bf18..52fea79152e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-5.c
@@ -13,7 +13,7 @@  void test1 (size_t size)
   char *buf = __builtin_malloc (size);
   if (!buf) return;
 
-  buf[size] = '\0'; /* { dg-warning "overflow" } */
+  buf[size] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
   free (buf);
 }
 
@@ -22,7 +22,7 @@  void test2 (size_t size)
   char *buf = __builtin_malloc (size);
   if (!buf) return;
 
-  buf[size + 1] = '\0'; /* { dg-warning "overflow" } */
+  buf[size + 1] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
   free (buf);
 }
 
@@ -31,33 +31,33 @@  void test3 (size_t size, size_t op)
   char *buf = __builtin_malloc (size);
   if (!buf) return;
 
-  buf[size + op] = '\0'; /* { dg-warning "overflow" } */
+  buf[size + op] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
   free (buf);
 }
 
 void test4 (size_t size, unsigned short s)
 {
   char *buf = __builtin_alloca (size);
-  buf[size + s] = '\0'; /* { dg-warning "overflow" } */
+  buf[size + s] = '\0'; /* { dg-warning "stack-based buffer overflow" } */
 }
 
 void test5 (size_t size)
 {
   int32_t *buf = __builtin_alloca (4 * size);
-  buf[size] = 42; /* { dg-warning "overflow" } */
+  buf[size] = 42; /* { dg-warning "stack-based buffer overflow" } */
 }
 
 void test6 (size_t size)
 {
   int32_t *buf = __builtin_alloca (4 * size);
   memset (buf, 0, 4 * size);
-  int32_t last = *(buf + 4 * size); /* { dg-warning "overread" } */
+  int32_t last = *(buf + 4 * size); /* { dg-warning "stack-based buffer over-read" } */
 }
 
 void test7 (size_t size)
 {
   int32_t *buf = __builtin_alloca (4 * size + 3); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */
-  buf[size] = 42; /* { dg-warning "overflow" } */
+  buf[size] = 42; /* { dg-warning "stack-based buffer overflow" } */
 }
 
 /* Test where the offset itself is not out-of-bounds
@@ -68,7 +68,7 @@  void test8 (size_t size, size_t offset)
   char src[size];
   char dst[size];
   memcpy (dst, src, size + offset); /* { dg-line test8 } */
-  /* { dg-warning "overread" "warning" { target *-*-* } test8 } */
+  /* { dg-warning "over-read" "warning" { target *-*-* } test8 } */
   /* { dg-warning "overflow" "warning" { target *-*-* } test8 } */
 }
 
@@ -77,7 +77,7 @@  void test9 (size_t size, size_t offset)
   int32_t src[size];
   int32_t dst[size];
   memcpy (dst, src, 4 * size + 1); /* { dg-line test9 } */
-  /* { dg-warning "overread" "warning" { target *-*-* } test9 } */
+  /* { dg-warning "over-read" "warning" { target *-*-* } test9 } */
   /* { dg-warning "overflow" "warning" { target *-*-* } test9 } */
 }
 
@@ -151,6 +151,6 @@  char *test99 (const char *x, const char *y)
   __builtin_memcpy (result, x, len_x);
   __builtin_memcpy (result + len_x, y, len_y);
   /* BUG (symptom): off-by-one out-of-bounds write to heap.  */
-  result[len_x + len_y] = '\0'; /* { dg-warning "overflow" } */
+  result[len_x + len_y] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
   return result;
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c
index 172ec474c42..ef460f4e772 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-container_of.c
@@ -44,8 +44,8 @@  int test (struct outer *outer_p, struct inner *inner_p)
   sum += o->i; /* { dg-line testB } */
 
   return sum;
-  /* { dg-warning "underread" "warning" { target *-*-* } testA } */
+  /* { dg-warning "stack-based buffer under-read" "warning" { target *-*-* } testA } */
   /* { dg-message "" "note" { target *-*-* } testA } */
-  /* { dg-warning "underread" "warning" { target *-*-* } testB } */
+  /* { dg-warning "stack-based buffer under-read" "warning" { target *-*-* } testB } */
   /* { dg-message "" "note" { target *-*-* } testB } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c
index 2b43000f833..f6d0dda9fb9 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-char-arr.c
@@ -1,50 +1,56 @@ 
 char arr[10]; /* { dg-message "capacity is 10 bytes" } */
 
-char int_arr_read_element_before_start_far(void)
+char char_arr_read_element_before_start_far(void)
 {
-  return arr[-100]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-100]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte -100 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-char int_arr_read_element_before_start_near(void)
+char char_arr_read_element_before_start_near(void)
 {
-  return arr[-2]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-2]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte -2 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-char int_arr_read_element_before_start_off_by_one(void)
+char char_arr_read_element_before_start_off_by_one(void)
 {
-  return arr[-1]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-1]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-char int_arr_read_element_at_start(void)
+char char_arr_read_element_at_start(void)
 {
   return arr[0];
 }
 
-char int_arr_read_element_at_end(void)
+char char_arr_read_element_at_end(void)
 {
   return arr[9];
 }
 
-char int_arr_read_element_after_end_off_by_one(void)
+char char_arr_read_element_after_end_off_by_one(void)
 {
-  return arr[10]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[10]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte 10 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 1 byte from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
-char int_arr_read_element_after_end_near(void)
+char char_arr_read_element_after_end_near(void)
 {
-  return arr[11]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[11]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte 11 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 1 byte from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
-char int_arr_read_element_after_end_far(void)
+char char_arr_read_element_after_end_far(void)
 {
-  return arr[100]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[100]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read at byte 100 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 1 byte from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c
index 0dc95563620..f1b6e119777 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-int-arr.c
@@ -4,20 +4,23 @@  int32_t arr[10]; /* { dg-message "capacity is 40 bytes" } */
 
 int32_t int_arr_read_element_before_start_far(void)
 {
-  return arr[-100]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-100]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte -400 till byte -397 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
 int32_t int_arr_read_element_before_start_near(void)
 {
-  return arr[-2]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-2]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
 int32_t int_arr_read_element_before_start_off_by_one(void)
 {
-  return arr[-1]; /* { dg-warning "buffer underread" "warning" } */
+  return arr[-1]; /* { dg-warning "buffer under-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte -4 till byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
 int32_t int_arr_read_element_at_start(void)
@@ -32,21 +35,24 @@  int32_t int_arr_read_element_at_end(void)
 
 int32_t int_arr_read_element_after_end_off_by_one(void)
 {
-  return arr[10]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[10]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte 40 till byte 43 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
 int32_t int_arr_read_element_after_end_near(void)
 {
-  return arr[11]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[11]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte 44 till byte 47 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
 int32_t int_arr_read_element_after_end_far(void)
 {
-  return arr[100]; /* { dg-warning "buffer overread" "warning" } */
+  return arr[100]; /* { dg-warning "buffer over-read" "warning" } */
   /* { dg-message "out-of-bounds read from byte 400 till byte 403 but 'arr' ends at byte 40" "final event" { target *-*-* } .-1 } */
   /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-struct-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-struct-arr.c
new file mode 100644
index 00000000000..0f50bb92290
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-read-struct-arr.c
@@ -0,0 +1,65 @@ 
+#include <stdint.h>
+
+struct st
+{
+  char buf[16];
+  int32_t x;
+  int32_t y;
+};
+
+struct st arr[10];
+
+int32_t struct_arr_read_x_element_before_start_far(void)
+{
+  return arr[-100].x; /* { dg-warning "buffer under-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte -2384 till byte -2381 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+int32_t struct_arr_read_x_element_before_start_near(void)
+{
+  return arr[-2].x; /* { dg-warning "buffer under-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte -32 till byte -29 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+int32_t struct_arr_read_x_element_before_start_off_by_one(void)
+{
+  return arr[-1].x; /* { dg-warning "buffer under-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+int32_t struct_arr_read_x_element_at_start(void)
+{
+  return arr[0].x;
+}
+
+int32_t struct_arr_read_x_element_at_end(void)
+{
+  return arr[9].x;
+}
+
+int32_t struct_arr_read_x_element_after_end_off_by_one(void)
+{
+  return arr[10].x; /* { dg-warning "buffer over-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte 256 till byte 259 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
+
+int32_t struct_arr_read_x_element_after_end_near(void)
+{
+  return arr[11].x; /* { dg-warning "buffer over-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte 280 till byte 283 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
+
+int32_t struct_arr_read_x_element_after_end_far(void)
+{
+  return arr[100].x; /* { dg-warning "buffer over-read" "warning" } */
+  /* { dg-message "out-of-bounds read from byte 2416 till byte 2419 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "read of 4 bytes from after the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c
index 739ebb11590..2f3bbfa2dc2 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-char-arr.c
@@ -1,37 +1,37 @@ 
 char arr[10]; /* { dg-message "capacity is 10 bytes" } */
 
-void int_arr_write_element_before_start_far(char x)
+void char_arr_write_element_before_start_far(char x)
 {
-  arr[-100] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-100] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write at byte -100 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-void int_arr_write_element_before_start_near(char x)
+void char_arr_write_element_before_start_near(char x)
 {
-  arr[-2] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-2] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write at byte -2 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-void int_arr_write_element_before_start_off_by_one(char x)
+void char_arr_write_element_before_start_off_by_one(char x)
 {
-  arr[-1] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-1] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write at byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
-void int_arr_write_element_at_start(char x)
+void char_arr_write_element_at_start(char x)
 {
   arr[0] = x;
 }
 
-void int_arr_write_element_at_end(char x)
+void char_arr_write_element_at_end(char x)
 {
   arr[9] = x;
 }
 
-void int_arr_write_element_after_end_off_by_one(char x)
+void char_arr_write_element_after_end_off_by_one(char x)
 {
   arr[10] = x; /* { dg-warning "buffer overflow" "warning" } */
   /* { dg-message "out-of-bounds write at byte 10 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
@@ -39,7 +39,7 @@  void int_arr_write_element_after_end_off_by_one(char x)
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
-void int_arr_write_element_after_end_near(char x)
+void char_arr_write_element_after_end_near(char x)
 {
   arr[11] = x; /* { dg-warning "buffer overflow" "warning" } */
   /* { dg-message "out-of-bounds write at byte 11 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
@@ -47,7 +47,7 @@  void int_arr_write_element_after_end_near(char x)
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
 }
 
-void int_arr_write_element_after_end_far(char x)
+void char_arr_write_element_after_end_far(char x)
 {
   arr[100] = x; /* { dg-warning "buffer overflow" "warning" } */
   /* { dg-message "out-of-bounds write at byte 100 but 'arr' ends at byte 10" "final event" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c
index b2b37b92e01..0adb7899641 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-int-arr.c
@@ -4,21 +4,21 @@  int32_t arr[10]; /* { dg-message "capacity is 40 bytes" } */
 
 void int_arr_write_element_before_start_far(int32_t x)
 {
-  arr[-100] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-100] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write from byte -400 till byte -397 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
 void int_arr_write_element_before_start_near(int32_t x)
 {
-  arr[-2] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-2] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
 
 void int_arr_write_element_before_start_off_by_one(int32_t x)
 {
-  arr[-1] = x; /* { dg-warning "buffer underflow" "warning" } */
+  arr[-1] = x; /* { dg-warning "buffer underwrite" "warning" } */
   /* { dg-message "out-of-bounds write from byte -4 till byte -1 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
   /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-struct-arr.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-struct-arr.c
new file mode 100644
index 00000000000..cf6b458f44b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-write-struct-arr.c
@@ -0,0 +1,65 @@ 
+#include <stdint.h>
+
+struct st
+{
+  char buf[16];
+  int32_t x;
+  int32_t y;
+};
+
+struct st arr[10];
+
+void struct_arr_write_x_element_before_start_far(int32_t x)
+{
+  arr[-100].x = x; /* { dg-warning "buffer underwrite" "warning" } */
+  /* { dg-message "out-of-bounds write from byte -2384 till byte -2381 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+void struct_arr_write_x_element_before_start_near(int32_t x)
+{
+  arr[-2].x = x; /* { dg-warning "buffer underwrite" "warning" } */
+  /* { dg-message "out-of-bounds write from byte -32 till byte -29 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+void struct_arr_write_x_element_before_start_off_by_one(int32_t x)
+{
+  arr[-1].x = x; /* { dg-warning "buffer underwrite" "warning" } */
+  /* { dg-message "out-of-bounds write from byte -8 till byte -5 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+void struct_arr_write_x_element_at_start(int32_t x)
+{
+  arr[0].x = x;
+}
+
+void struct_arr_write_x_element_at_end(int32_t x)
+{
+  arr[9].x = x;
+}
+
+void struct_arr_write_x_element_after_end_off_by_one(int32_t x)
+{
+  arr[10].x = x; /* { dg-warning "buffer overflow" "warning" } */
+  /* { dg-message "out-of-bounds write from byte 256 till byte 259 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "write of 4 bytes to beyond the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
+
+void struct_arr_write_x_element_after_end_near(int32_t x)
+{
+  arr[11].x = x; /* { dg-warning "buffer overflow" "warning" } */
+  /* { dg-message "out-of-bounds write from byte 280 till byte 283 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "write of 4 bytes to beyond the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
+
+void struct_arr_write_x_element_after_end_far(int32_t x)
+{
+  arr[100].x = x; /* { dg-warning "buffer overflow" "warning" } */
+  /* { dg-message "out-of-bounds write from byte 2416 till byte 2419 but 'arr' ends at byte 240" "final event" { target *-*-* } .-1 } */
+  /* { dg-message "write of 4 bytes to beyond the end of 'arr'" "num bad bytes note" { target *-*-* } .-2 } */
+  /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-3 } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101962.c b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
index cf0041b2fcd..08c0aba5cbf 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101962.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
@@ -25,7 +25,7 @@  test_1 (void)
   return *a; /* { dg-line test_1 } */
 
   /* { dg-warning "use of uninitialized value '\\*a'" "warning" { target *-*-* } test_1 } */
-  /* { dg-warning "overread" "warning" { target *-*-* } test_1 } */
+  /* { dg-warning "stack-based buffer over-read" "warning" { target *-*-* } test_1 } */
 }
 
 static const char * __attribute__((noinline))
diff --git a/gcc/testsuite/gcc.dg/analyzer/realloc-5.c b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
index 2efe3371e12..75f0b70a996 100644
--- a/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/realloc-5.c
@@ -37,7 +37,7 @@  void test_1 ()
       __analyzer_eval (q[8] == 1); /* { dg-line eval } */
     
       /* { dg-warning "UNKNOWN" "warning" { target *-*-* } eval } */
-      /* { dg-warning "overread" "warning" { target *-*-* } eval } */
+      /* { dg-warning "heap-based buffer over-read" "warning" { target *-*-* } eval } */
       /* { dg-warning "use of uninitialized value" "warning" { target *-*-* } eval } */
     }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
index b05b8629a7f..def83006a71 100644
--- a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c
@@ -184,7 +184,7 @@  static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e,
       mask = (1 << w) - 1;
       /* The analyzer thinks that h can be -1 here.
          This is probably a false positive. */
-      while ((i & mask) !=  x[h]) { /* { dg-bogus "underread" "" { xfail *-*-* } } */
+      while ((i & mask) !=  x[h]) { /* { dg-bogus "under-read" "" { xfail *-*-* } } */
         h--;
         w -= l;
         mask = (1 << w) - 1;