diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index d7b669a4e38e..a51d594b5b2c 100644
--- a/gcc/analyzer/access-diagram.cc
+++ b/gcc/analyzer/access-diagram.cc
@@ -1509,10 +1509,16 @@ public:
       out.add_all_bytes_in_range (m_actual_bits);
     else
       {
-	byte_range head_of_string (0, m_ellipsis_head_len);
+	byte_range bytes (0, 0);
+	bool valid = m_actual_bits.as_concrete_byte_range (&bytes);
+	gcc_assert (valid);
+	byte_range head_of_string (bytes.get_start_byte_offset (),
+				   m_ellipsis_head_len);
 	out.add_all_bytes_in_range (head_of_string);
 	byte_range tail_of_string
-	  (TREE_STRING_LENGTH (string_cst) - m_ellipsis_tail_len,
+	  ((bytes.get_start_byte_offset ()
+	    + TREE_STRING_LENGTH (string_cst)
+	    - m_ellipsis_tail_len),
 	   m_ellipsis_tail_len);
 	out.add_all_bytes_in_range (tail_of_string);
 	/* Adding the above pair of ranges will also effectively add
@@ -1535,11 +1541,14 @@ public:
     tree string_cst = get_string_cst ();
     if (m_show_full_string)
       {
-       for (byte_offset_t byte_idx = bytes.get_start_byte_offset ();
-	    byte_idx < bytes.get_next_byte_offset ();
-	    byte_idx = byte_idx + 1)
-	 add_column_for_byte (t, btm, sm, byte_idx,
-			      byte_idx_table_y, byte_val_table_y);
+       for (byte_offset_t byte_idx_within_cluster
+	      = bytes.get_start_byte_offset ();
+	    byte_idx_within_cluster < bytes.get_next_byte_offset ();
+	    byte_idx_within_cluster = byte_idx_within_cluster + 1)
+	 add_column_for_byte
+	   (t, btm, sm, byte_idx_within_cluster,
+	    byte_idx_within_cluster - bytes.get_start_byte_offset (),
+	    byte_idx_table_y, byte_val_table_y);
 
        if (m_show_utf8)
 	 {
@@ -1566,10 +1575,13 @@ public:
 		 = decoded_char.m_start_byte - TREE_STRING_POINTER (string_cst);
 	       byte_size_t size_in_bytes
 		 = decoded_char.m_next_byte - decoded_char.m_start_byte;
-	       byte_range bytes (start_byte_idx, size_in_bytes);
+	       byte_range cluster_bytes_for_codepoint
+		 (start_byte_idx + bytes.get_start_byte_offset (),
+		  size_in_bytes);
 
 	       const table::rect_t code_point_table_rect
-		 = btm.get_table_rect (&m_string_reg, bytes,
+		 = btm.get_table_rect (&m_string_reg,
+				       cluster_bytes_for_codepoint,
 				       utf8_code_point_table_y, 1);
 	       char buf[100];
 	       sprintf (buf, "U+%04x", decoded_char.m_ch);
@@ -1579,7 +1591,8 @@ public:
 	       if (show_unichars)
 		 {
 		   const table::rect_t character_table_rect
-		     = btm.get_table_rect (&m_string_reg, bytes,
+		     = btm.get_table_rect (&m_string_reg,
+					   cluster_bytes_for_codepoint,
 					   utf8_character_table_y, 1);
 		   if (cpp_is_printable_char (decoded_char.m_ch))
 		     t.set_cell_span (character_table_rect,
@@ -1598,12 +1611,14 @@ public:
       {
 	/* Head of string.  */
 	for (int byte_idx = 0; byte_idx < m_ellipsis_head_len; byte_idx++)
-	  add_column_for_byte (t, btm, sm, byte_idx,
+	  add_column_for_byte (t, btm, sm,
+			       byte_idx + bytes.get_start_byte_offset (),
+			       byte_idx,
 			       byte_idx_table_y, byte_val_table_y);
 
 	/* Ellipsis (two rows high).  */
 	const byte_range ellipsis_bytes
-	  (m_ellipsis_head_len,
+	  (m_ellipsis_head_len + bytes.get_start_byte_offset (),
 	   TREE_STRING_LENGTH (string_cst)
 	   - (m_ellipsis_head_len + m_ellipsis_tail_len));
 	const table::rect_t table_rect
@@ -1616,7 +1631,9 @@ public:
 	       = (TREE_STRING_LENGTH (string_cst) - m_ellipsis_tail_len);
 	     byte_idx < TREE_STRING_LENGTH (string_cst);
 	     byte_idx++)
-	  add_column_for_byte (t, btm, sm, byte_idx,
+	  add_column_for_byte (t, btm, sm,
+			       byte_idx + bytes.get_start_byte_offset (),
+			       byte_idx,
 			       byte_idx_table_y, byte_val_table_y);
       }
 
@@ -1660,25 +1677,27 @@ private:
 
   void add_column_for_byte (table &t, const bit_to_table_map &btm,
 			    style_manager &sm,
-			    const byte_offset_t byte_idx,
+			    const byte_offset_t byte_idx_within_cluster,
+			    const byte_offset_t byte_idx_within_string,
 			    const int byte_idx_table_y,
 			    const int byte_val_table_y) const
   {
     tree string_cst = get_string_cst ();
-    gcc_assert (byte_idx >= 0);
-    gcc_assert (byte_idx < TREE_STRING_LENGTH (string_cst));
+    gcc_assert (byte_idx_within_string >= 0);
+    gcc_assert (byte_idx_within_string < TREE_STRING_LENGTH (string_cst));
 
-    const byte_range bytes (byte_idx, 1);
+    const byte_range bytes (byte_idx_within_cluster, 1);
     if (1) // show_byte_indices
       {
 	const table::rect_t idx_table_rect
 	  = btm.get_table_rect (&m_string_reg, bytes, byte_idx_table_y, 1);
 	t.set_cell_span (idx_table_rect,
 			 fmt_styled_string (sm, "[%li]",
-					    byte_idx.ulow ()));
+					    byte_idx_within_string.ulow ()));
       }
 
-    char byte_val = TREE_STRING_POINTER (string_cst)[byte_idx.ulow ()];
+    char byte_val
+      = TREE_STRING_POINTER (string_cst)[byte_idx_within_string.ulow ()];
     const table::rect_t val_table_rect
       = btm.get_table_rect (&m_string_reg, bytes, byte_val_table_y, 1);
     table_cell_content content (make_cell_content_for_byte (sm, byte_val));
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-17.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-17.c
new file mode 100644
index 000000000000..6920e8c776fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-17.c
@@ -0,0 +1,34 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void test (void)
+{
+  char buf[10];
+  strcpy (buf, "hello");
+  strcat (buf, " world!"); /* { dg-warning "stack-based buffer overflow" } */
+  /* { dg-message "write of 3 bytes to beyond the end of 'buf'" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+                           ┌─────┬─────┬────┬────┬────┐┌─────┬─────┬─────┐
+                           │ [0] │ [1] │[2] │[3] │[4] ││ [5] │ [6] │ [7] │
+                           ├─────┼─────┼────┼────┼────┤├─────┼─────┼─────┤
+                           │ ' ' │ 'w' │'o' │'r' │'l' ││ 'd' │ '!' │ NUL │
+                           ├─────┴─────┴────┴────┴────┴┴─────┴─────┴─────┤
+                           │      string literal (type: 'char[8]')       │
+                           └─────────────────────────────────────────────┘
+                              │     │    │    │    │      │     │     │
+                              │     │    │    │    │      │     │     │
+                              v     v    v    v    v      v     v     v
+  ┌─────┬────────────────────────────────────────┬────┐┌─────────────────┐
+  │ [0] │                  ...                   │[9] ││                 │
+  ├─────┴────────────────────────────────────────┴────┤│after valid range│
+  │             'buf' (type: 'char[10]')              ││                 │
+  └───────────────────────────────────────────────────┘└─────────────────┘
+  ├─────────────────────────┬─────────────────────────┤├────────┬────────┤
+                            │                                   │
+                  ╭─────────┴────────╮                ╭─────────┴─────────╮
+                  │capacity: 10 bytes│                │overflow of 3 bytes│
+                  ╰──────────────────╯                ╰───────────────────╯
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-18.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-18.c
new file mode 100644
index 000000000000..ea0b88019cd9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-18.c
@@ -0,0 +1,38 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void test (void)
+{
+  char buf[11];
+  strcpy (buf, "サツキ");
+  strcat (buf, "メイ"); /* { dg-warning "stack-based buffer overflow" } */
+  /* { dg-message "write of 5 bytes to beyond the end of 'buf'" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+                             ┌─────┬─────────┐┌────┬────┬────┬────┬──────┐
+                             │ [0] │   [1]   ││[2] │[3] │[4] │[5] │ [6]  │
+                             ├─────┼─────────┤├────┼────┼────┼────┼──────┤
+                             │0xe3 │  0x83   ││0xa1│0xe3│0x82│0xa4│ 0x00 │
+                             ├─────┴─────────┴┴────┼────┴────┴────┼──────┤
+                             │       U+30e1        │    U+30a4    │U+0000│
+                             ├─────────────────────┼──────────────┼──────┤
+                             │         メ          │      イ      │ NUL  │
+                             ├─────────────────────┴──────────────┴──────┤
+                             │     string literal (type: 'char[7]')      │
+                             └───────────────────────────────────────────┘
+                                │       │       │    │    │    │     │
+                                │       │       │    │    │    │     │
+                                v       v       v    v    v    v     v
+  ┌────┬───────────────────────────┬─────────┐┌──────────────────────────┐
+  │[0] │            ...            │  [10]   ││                          │
+  ├────┴───────────────────────────┴─────────┤│    after valid range     │
+  │         'buf' (type: 'char[11]')         ││                          │
+  └──────────────────────────────────────────┘└──────────────────────────┘
+  ├────────────────────┬─────────────────────┤├────────────┬─────────────┤
+                       │                                   │
+             ╭─────────┴────────╮                ╭─────────┴─────────╮
+             │capacity: 11 bytes│                │overflow of 5 bytes│
+             ╰──────────────────╯                ╰───────────────────╯
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c
new file mode 100644
index 000000000000..35ab72b6efc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c
@@ -0,0 +1,45 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode -Wno-stringop-overflow" } */
+/* { dg-skip-if "" { powerpc-ibm-aix* } } */
+
+#include <string.h>
+
+#define LOREM_IPSUM \
+  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod" \
+  " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim" \
+  " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea" \
+  " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate" \
+  " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint" \
+  " occaecat cupidatat non proident, sunt in culpa qui officia deserunt" \
+  " mollit anim id est laborum."
+
+void
+test_long_string ()
+{
+  char buf[100];
+  strcpy (buf, "abc ");
+  strcat (buf, LOREM_IPSUM); /* { dg-warning "stack-based buffer overflow" } */
+  /* { dg-message "write of 350 bytes to beyond the end of 'buf'" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+        ┌───┬───┬───┬───┬───┬───┬───────┬─────┬─────┬─────┬─────┬─────┬─────┐
+        │[0]│[1]│[2]│[3]│[4]│[5]│       │[440]│[441]│[442]│[443]│[444]│[445]│
+        ├───┼───┼───┼───┼───┼───┤  ...  ├─────┼─────┼─────┼─────┼─────┼─────┤
+        │'L'│'o'│'r'│'e'│'m'│' '│       │ 'o' │ 'r' │ 'u' │ 'm' │ '.' │ NUL │
+        ├───┴───┴───┴───┴───┴───┴───────┴─────┴─────┴─────┴─────┴─────┴─────┤
+        │                string literal (type: 'char[446]')                 │
+        └───────────────────────────────────────────────────────────────────┘
+          │   │   │   │   │   │ │  │   │   │     │     │     │     │     │
+          │   │   │   │   │   │ │  │   │   │     │     │     │     │     │
+          v   v   v   v   v   v v  v   v   v     v     v     v     v     v
+  ┌───┬──────────────────────────┬────┐┌────────────────────────────────────┐
+  │[0]│           ...            │[99]││                                    │
+  ├───┴──────────────────────────┴────┤│         after valid range          │
+  │     'buf' (type: 'char[100]')     ││                                    │
+  └───────────────────────────────────┘└────────────────────────────────────┘
+  ├─────────────────┬─────────────────┤├─────────────────┬──────────────────┤
+                    │                                    │
+          ╭─────────┴─────────╮               ╭──────────┴──────────╮
+          │capacity: 100 bytes│               │overflow of 350 bytes│
+          ╰───────────────────╯               ╰─────────────────────╯
+   { dg-end-multiline-output "" } */
