aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/analyzer
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/analyzer')
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/data-model-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c5
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c40
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c13
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c24
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c29
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c82
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c53
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c43
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c110
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c30
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c45
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c45
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c40
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c125
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c36
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c34
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr101962.c2
25 files changed, 1045 insertions, 10 deletions
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
index 86d1ccf..3c4a45f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
@@ -240,8 +240,8 @@ void test_16 (void)
__analyzer_eval (strlen (msg) == 11); /* { dg-warning "TRUE" } */
/* Out-of-bounds. */
- __analyzer_eval (msg[100] == 'e'); /* { dg-warning "UNKNOWN" } */
- // TODO: some kind of warning for the out-of-bounds access
+ __analyzer_eval (msg[100] == 'e'); /* { dg-warning "UNKNOWN" "eval result" } */
+ /* { dg-warning "buffer over-read" "out-of-bounds" { target *-*-* } .-1 } */
}
static const char *__attribute__((noinline))
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
index f08aee6..9134bb4 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
@@ -12,11 +12,6 @@ int test (void *ptr)
WRAPPED_FREE (ptr); /* { dg-message "in expansion of macro 'WRAPPED_FREE'" } */
WRAPPED_FREE (ptr); /* { dg-message "in expansion of macro 'WRAPPED_FREE'" } */
- /* Erase the spans indicating the header file
- (to avoid embedding path assumptions). */
- /* { dg-regexp "\[^|\]+/malloc-macro.h:\[0-9\]+:\[0-9\]+:" } */
- /* { dg-regexp "\[^|\]+/malloc-macro.h:\[0-9\]+:\[0-9\]+:" } */
-
/* { dg-begin-multiline-output "" }
NN | #define WRAPPED_FREE(PTR) free(PTR)
| ^~~~~~~~~
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c
new file mode 100644
index 0000000..5e6eadc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ +--------------------------------+
+ |write from 'x' (type: 'int32_t')|
+ +--------------------------------+
+ |
+ |
+ v
+ +--------+-----------------+---------++--------------------------------+
+ | [0] | ... | [9] || |
+ +--------+-----------------+---------+| after valid range |
+ | 'arr' (type: 'int32_t[10]') || |
+ +------------------------------------++--------------------------------+
+ |~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~|
+ | |
+ +---------+--------+ +---------+---------+
+ |capacity: 40 bytes| |overflow of 4 bytes|
+ +------------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c
new file mode 100644
index 0000000..4c4d9d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c
@@ -0,0 +1,40 @@
+/* Test of -fanalyzer-debug-text-art. */
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii -fanalyzer-debug-text-art" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+/* { dg-begin-multiline-output "" }
+
+ +---------+-----------+-----------+---+--------------------------------+
+ | tc0 | tc1 | tc2 |tc3| tc4 |
+ +---------+-----------+-----------+---+--------------------------------+
+ |bytes 0-3|bytes 4-35 |bytes 36-39| | bytes 40-43 |
+ +---------+-----------+-----------+ +--------------------------------+
+ +--------------------------------+
+ |write from 'x' (type: 'int32_t')|
+ +--------------------------------+
+ |
+ |
+ v
+ +---------+-----------+-----------+ +--------------------------------+
+ | [0] | ... | [9] | | |
+ +---------+-----------+-----------+ | after valid range |
+ | 'arr' (type: 'int32_t[10]') | | |
+ +---------------------------------+ +--------------------------------+
+ |~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~|
+ | |
+ +---------+--------+ +---------+---------+
+ |capacity: 40 bytes| |overflow of 4 bytes|
+ +------------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
new file mode 100644
index 0000000..1c61252
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=emoji" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────────┐
+ │write from 'x' (type: 'int32_t')│
+ └────────────────────────────────┘
+ │
+ │
+ v
+ ┌────────┬─────────────────┬─────────┐┌────────────────────────────────┐
+ │ [0] │ ... │ [9] ││ │
+ ├────────┴─────────────────┴─────────┤│ after valid range │
+ │ 'arr' (type: 'int32_t[10]') ││ │
+ └────────────────────────────────────┘└────────────────────────────────┘
+ ├─────────────────┬──────────────────┤├───────────────┬────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭───────────┴──────────╮
+ │capacity: 40 bytes│ │⚠️ overflow of 4 bytes│
+ ╰──────────────────╯ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c
new file mode 100644
index 0000000..0a2cc34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c
@@ -0,0 +1,13 @@
+/* { dg-additional-options "-fdiagnostics-format=json-file" } */
+
+/* The custom JSON format doesn't support text art, so this is just a simple
+ smoketext. */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c
new file mode 100644
index 0000000..051a1ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c
@@ -0,0 +1,24 @@
+/* We require -fdiagnostics-text-art-charset= to get any text art here
+ because of the test suite using -fdiagnostics-plain-output. */
+
+/* { dg-additional-options "-fdiagnostics-format=sarif-file -fdiagnostics-text-art-charset=ascii" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x;
+}
+
+/* Verify that some JSON was written to a file with the expected name.
+
+ { dg-final { verify-sarif-file } }
+
+ Expect the "alt-text" to be captured.
+ { dg-final { scan-sarif-file "\"text\": \"Diagram visualizing the predicted out-of-bounds access\"," } }
+
+ Expect the diagram to have 4 leading spaces (to indicate a code block),
+ and that at least part of the diagram was written out.
+ { dg-final { scan-sarif-file "\"markdown\": \" .*capacity: 40 bytes.*\"" } } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
new file mode 100644
index 0000000..71f66ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────────┐
+ │write from 'x' (type: 'int32_t')│
+ └────────────────────────────────┘
+ │
+ │
+ v
+ ┌────────┬─────────────────┬─────────┐┌────────────────────────────────┐
+ │ [0] │ ... │ [9] ││ │
+ ├────────┴─────────────────┴─────────┤│ after valid range │
+ │ 'arr' (type: 'int32_t[10]') ││ │
+ └────────────────────────────────────┘└────────────────────────────────┘
+ ├─────────────────┬──────────────────┤├───────────────┬────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 40 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c
new file mode 100644
index 0000000..4a7b8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c
@@ -0,0 +1,29 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+int32_t int_vla_write_element_symbolic_before_start (int32_t x, size_t n)
+{
+ int32_t arr[n]; /* { dg-message "\\(1\\) capacity: 'n \\* 4' bytes" } */
+ arr[-2] = 42; /* { dg-warning "stack-based buffer underwrite" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────┐
+ │write of '(int) 42'│
+ └───────────────────┘
+ │
+ │
+ v
+ ┌───────────────────┐ ┌────────────────────────────────┐
+ │before valid range │ │buffer allocated on stack at (1)│
+ └───────────────────┘ └────────────────────────────────┘
+ ├─────────┬─────────┤├───────┬───────┤├───────────────┬────────────────┤
+ │ │ │
+ ╭─────────┴───────────╮ ╭───┴───╮ ╭───────────┴───────────╮
+ │underwrite of 4 bytes│ │4 bytes│ │capacity: 'n * 4' bytes│
+ ╰─────────────────────╯ ╰───────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c
new file mode 100644
index 0000000..f8eb158
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c
@@ -0,0 +1,82 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+/* { dg-require-effective-target alloca } */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+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 "stack-based buffer over-read" } */
+}
+
+/* (size * 16) - (size * 4) leads to a gap of (size * 12). */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────┐
+ │ read of 4 bytes │
+ └─────────────────┘
+ ^
+ │
+ │
+ ┌────────────────────────────────┐ ┌─────────────────┐
+ │buffer allocated on stack at (1)│ │after valid range│
+ └────────────────────────────────┘ └─────────────────┘
+ ├───────────────┬────────────────┤├────────┬────────┤├────────┬────────┤
+ │ │ │
+ │ │ ╭──────────┴─────────╮
+ │ │ │over-read of 4 bytes│
+ │ │ ╰────────────────────╯
+ ╭───────────┴──────────╮ ╭────────┴────────╮
+ │size: 'size * 4' bytes│ │'size * 12' bytes│
+ ╰──────────────────────╯ ╰─────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+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 "stack-based buffer overflow" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────────────────────────┐
+ │ write of '(int) 42' │
+ └───────────────────────────────────────┘
+ │ │
+ │ │
+ v v
+ ┌──────────────────────────────────────────────────┐┌──────────────────┐
+ │ buffer allocated on stack at (1) ││after valid range │
+ └──────────────────────────────────────────────────┘└──────────────────┘
+ ├────────────────────────┬─────────────────────────┤├────────┬─────────┤
+ │ │
+ ╭───────────────┴──────────────╮ ╭─────────┴────────╮
+ │capacity: 'size * 4 + 3' bytes│ │overflow of 1 byte│
+ ╰──────────────────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+
+/* We're currently not able to generate a diagram for this case;
+ make sure we handle this case gracefully. */
+
+char *test99 (const char *x, const char *y)
+{
+ size_t len_x = __builtin_strlen (x);
+ size_t len_y = __builtin_strlen (y);
+ /* BUG (root cause): forgot to add 1 for terminator. */
+ size_t sz = len_x + len_y;
+ char *result = __builtin_malloc (sz);
+ if (!result)
+ return NULL;
+ __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 "heap-based buffer overflow" } */
+ return result;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c
new file mode 100644
index 0000000..3573750
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c
@@ -0,0 +1,53 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+/* { dg-require-effective-target alloca } */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+void test8 (size_t size, size_t offset)
+{
+ char src[size];
+ char dst[size];
+ memcpy (dst, src, size + offset); /* { dg-line test8 } */
+ /* { dg-warning "over-read" "warning" { target *-*-* } test8 } */
+ /* { dg-warning "overflow" "warning" { target *-*-* } test8 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ read of 'size + offset' bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ ^ ^
+ │ │
+ │ │
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────────┴─────────────╮
+ │size: 'size' bytes│ │over-read of 'offset' bytes│
+ ╰──────────────────╯ ╰───────────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 'size + offset' bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │
+ │ │
+ v v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭───────────┴──────────╮ ╭─────────────┴────────────╮
+ │capacity: 'size' bytes│ │overflow of 'offset' bytes│
+ ╰──────────────────────╯ ╰──────────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c
new file mode 100644
index 0000000..dcd1263
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c
@@ -0,0 +1,43 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[9];
+ strcpy (buf, "Liberté\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 10 bytes into a region of size 9 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* Example of non-ASCII UTF-8 that's short enough to fully quote, whilst
+ containing control characters. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬──────┬──────┬──────┬────┬────┬──────┐┌─────────────────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │[6] │[7] │ [8] ││ [9] │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┼────┼──────┤├─────────────────┤
+ │ 0x4c │ 0x69 │ 0x62 │ 0x65 │ 0x72 │ 0x74 │0xc3│0xa9│ 0x0a ││ 0x00 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┴────┼──────┤├─────────────────┤
+ │U+004c│U+0069│U+0062│U+0065│U+0072│U+0074│ U+00e9 │U+000a││ U+0000 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼─────────┼──────┤├─────────────────┤
+ │ L │ i │ b │ e │ r │ t │ é │ ││ NUL │
+ ├──────┴──────┴──────┴──────┴──────┴──────┴─────────┴──────┴┴─────────────────┤
+ │ string literal (type: 'char[10]') │
+ └─────────────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v
+ ┌──────┬────────────────────────────────────────────┬──────┐┌─────────────────┐
+ │ [0] │ ... │ [8] ││ │
+ ├──────┴────────────────────────────────────────────┴──────┤│after valid range│
+ │ 'buf' (type: 'char[9]') ││ │
+ └──────────────────────────────────────────────────────────┘└─────────────────┘
+ ├────────────────────────────┬─────────────────────────────┤├────────┬────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴────────╮
+ │capacity: 9 bytes│ │overflow of 1 byte│
+ ╰─────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c
new file mode 100644
index 0000000..3cedf06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c
@@ -0,0 +1,110 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+
+extern int32_t arr_0[0]; /* { dg-message "capacity: 0 bytes" } */
+extern int32_t arr_1[1]; /* { dg-message "capacity: 4 bytes" } */
+extern int32_t arr_2[2]; /* { dg-message "capacity: 8 bytes" } */
+extern int32_t arr_3[3]; /* { dg-message "capacity: 12 bytes" } */
+extern int32_t arr_4[4]; /* { dg-message "capacity: 16 bytes" } */
+
+void test_immediately_after (int x)
+{
+ arr_0[0] = x; /* { dg-warning "buffer overflow" } */
+ arr_1[1] = x; /* { dg-warning "buffer overflow" } */
+ arr_2[2] = x; /* { dg-warning "buffer overflow" } */
+ arr_3[3] = x; /* { dg-warning "buffer overflow" } */
+ arr_4[4] = x; /* { dg-warning "buffer overflow" } */
+}
+
+/* Expect no diagram for the arr_0 case: there's no valid region
+to write to. */
+
+/* The arr_1 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write from 'x' (type: 'int') │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ [0] ││ │
+ ├──────────────────────────────────┤│ after valid range │
+ │ 'arr_1' (type: 'int32_t[1]') ││ │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 4 bytes│ │overflow of 4 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_2 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌────────────────────┬───────────────────┐┌────────────────────────────┐
+ │ [0] │ [1] ││ │
+ ├────────────────────┴───────────────────┤│ after valid range │
+ │ 'arr_2' (type: 'int32_t[2]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 8 bytes│ │overflow of 4 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_3 case. */
+// Perhaps we should show [1] rather than ellipsize here.
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌─────────────┬─────────────┬────────────┐┌────────────────────────────┐
+ │ [0] │ ... │ [2] ││ │
+ ├─────────────┴─────────────┴────────────┤│ after valid range │
+ │ 'arr_3' (type: 'int32_t[3]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 12 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_4 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────┬──────────────────┬──────────┐┌────────────────────────────┐
+ │ [0] │ ... │ [3] ││ │
+ ├──────────┴──────────────────┴──────────┤│ after valid range │
+ │ 'arr_4' (type: 'int32_t[4]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 16 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c
new file mode 100644
index 0000000..e2a6381
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c
@@ -0,0 +1,42 @@
+/* Regression test for ICE with short values of
+ --param=analyzer-text-art-string-ellipsis-threshold=. */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode --param=analyzer-text-art-string-ellipsis-threshold=0" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[9];
+ strcpy (buf, "Liberté\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 10 bytes into a region of size 9 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬──────┬──────┬──────┬────┬────┬──────┐┌─────────────────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │[6] │[7] │ [8] ││ [9] │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┼────┼──────┤├─────────────────┤
+ │ 0x4c │ 0x69 │ 0x62 │ 0x65 │ 0x72 │ 0x74 │0xc3│0xa9│ 0x0a ││ 0x00 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┴────┼──────┤├─────────────────┤
+ │U+004c│U+0069│U+0062│U+0065│U+0072│U+0074│ U+00e9 │U+000a││ U+0000 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼─────────┼──────┤├─────────────────┤
+ │ L │ i │ b │ e │ r │ t │ é │ ││ NUL │
+ ├──────┴──────┴──────┴──────┴──────┴──────┴─────────┴──────┴┴─────────────────┤
+ │ string literal (type: 'char[10]') │
+ └─────────────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v
+ ┌──────┬────────────────────────────────────────────┬──────┐┌─────────────────┐
+ │ [0] │ ... │ [8] ││ │
+ ├──────┴────────────────────────────────────────────┴──────┤│after valid range│
+ │ 'buf' (type: 'char[9]') ││ │
+ └──────────────────────────────────────────────────────────┘└─────────────────┘
+ ├────────────────────────────┬─────────────────────────────┤├────────┬────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴────────╮
+ │capacity: 9 bytes│ │overflow of 1 byte│
+ ╰─────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c
new file mode 100644
index 0000000..535dab1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c
@@ -0,0 +1,30 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+void int_vla_write_element_after_end_off_by_one(int32_t x, size_t n)
+{
+ int32_t arr[n]; /* { dg-message "\\(1\\) capacity: 'n \\* 4' bytes" } */
+
+ arr[n] = x; /* { dg-warning "stack-based buffer overflow" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write from 'x' (type: 'int32_t') │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭───────────┴───────────╮ ╭─────────┴─────────╮
+ │capacity: 'n * 4' bytes│ │overflow of 4 bytes│
+ ╰───────────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c
new file mode 100644
index 0000000..064f3fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c
@@ -0,0 +1,45 @@
+/* The multiline output assumes sizeof(size_t) == 8.
+ { dg-require-effective-target lp64 } */
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+struct str {
+ size_t len;
+ char data[];
+};
+
+struct str *
+make_str_badly (const char *src)
+{
+ size_t len = strlen(src);
+ struct str *str = malloc(sizeof(str) + len); /* { dg-message "\\(1\\) capacity: 'len \\+ 8' bytes" } */
+ if (!str)
+ return NULL;
+ str->len = len;
+ memcpy(str->data, src, len);
+ str->data[len] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
+ return str;
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write of '(char) 0' │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on heap at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭────────────┴────────────╮ ╭─────────┴────────╮
+ │capacity: 'len + 8' bytes│ │overflow of 1 byte│
+ ╰─────────────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c
new file mode 100644
index 0000000..ec8e4ab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c
@@ -0,0 +1,45 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#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, LOREM_IPSUM); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 446 bytes into a region of size 100 overflows the destination" "" { 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 346 bytes│
+ ╰───────────────────╯ ╰─────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c
new file mode 100644
index 0000000..e82bce9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c
@@ -0,0 +1,40 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[5];
+ strcpy (buf, "文字化け"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 13 bytes into a region of size 5 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* Without unicode support, we shouldn't show the printable unicode chars. */
+
+/* { dg-begin-multiline-output "" }
+
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ | [0] | [1] | [2] |[3] |[4] ||[5] |[6] |[7] |[8] |[9] |[10]|[11]| [12] |
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ |0xe6 |0x96 |0x87 |0xe5|0xad||0x97|0xe5|0x8c|0x96|0xe3|0x81|0x91| 0x00 |
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ | U+6587 | U+5b57 | U+5316 | U+3051 |U+0000|
+ +-----------------+---------------+--------------+--------------+------+
+ | string literal (type: 'char[13]') |
+ +----------------------------------------------------------------------+
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ v v v v v v v v v v v v v
+ +-----+----------------+----++-----------------------------------------+
+ | [0] | ... |[4] || |
+ +-----+----------------+----+| after valid range |
+ | 'buf' (type: 'char[5]') || |
+ +---------------------------++-----------------------------------------+
+ |~~~~~~~~~~~~~+~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~|
+ | |
+ +--------+--------+ +---------+---------+
+ |capacity: 5 bytes| |overflow of 8 bytes|
+ +-----------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c
new file mode 100644
index 0000000..48fa12f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c
@@ -0,0 +1,42 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[5];
+ strcpy (buf, "文字化け"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 13 bytes into a region of size 5 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* With unicode support, we should show the printable unicode chars. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────┬─────┬─────┬────┬────┐┌────┬────┬────┬────┬────┬────┬────┬──────┐
+ │ [0] │ [1] │ [2] │[3] │[4] ││[5] │[6] │[7] │[8] │[9] │[10]│[11]│ [12] │
+ ├─────┼─────┼─────┼────┼────┤├────┼────┼────┼────┼────┼────┼────┼──────┤
+ │0xe6 │0x96 │0x87 │0xe5│0xad││0x97│0xe5│0x8c│0x96│0xe3│0x81│0x91│ 0x00 │
+ ├─────┴─────┴─────┼────┴────┴┴────┼────┴────┴────┼────┴────┴────┼──────┤
+ │ U+6587 │ U+5b57 │ U+5316 │ U+3051 │U+0000│
+ ├─────────────────┼───────────────┼──────────────┼──────────────┼──────┤
+ │ 文 │ 字 │ 化 │ け │ NUL │
+ ├─────────────────┴───────────────┴──────────────┴──────────────┴──────┤
+ │ string literal (type: 'char[13]') │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v v v v
+ ┌─────┬────────────────┬────┐┌─────────────────────────────────────────┐
+ │ [0] │ ... │[4] ││ │
+ ├─────┴────────────────┴────┤│ after valid range │
+ │ 'buf' (type: 'char[5]') ││ │
+ └───────────────────────────┘└─────────────────────────────────────────┘
+ ├─────────────┬─────────────┤├────────────────────┬────────────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 5 bytes│ │overflow of 8 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c
new file mode 100644
index 0000000..25bf9d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c
@@ -0,0 +1,125 @@
+/* { dg-require-effective-target lp64 }
+ Misbehaves with -m32 due to optimization turning the pointer arithmetic into:
+ _2 = &buf + 4294967246;
+ memcpy (_2, _1, 4096);
+*/
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#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."
+
+/* This memcpy reads from both before and after the bounds of the
+ string literal, and writes to both before and after the bounds of "buf". */
+
+void
+test_bad_memcpy ()
+{
+ char buf[100];
+ memcpy (buf - 50, LOREM_IPSUM - 100, 4096); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "stack-based buffer underwrite" "" { target *-*-* } .-1 } */
+ /* { dg-warning "buffer under-read" "" { target *-*-* } .-2 } */
+ /* { dg-warning "buffer over-read" "" { target *-*-* } .-3 } */
+ /* { dg-warning "'memcpy' writing 4096 bytes into a region of size 0 overflows the destination" "" { target *-*-* } .-4 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ read of 4096 bytes │
+ └─────────────────────────────────────────────────────────────────────────┘
+ ^ ^ ^ ^ ^
+ │ │ │ │ │
+ │ │ │ │ │
+ ┌──────────────────┐┌──────────┬──────────┬────────────┐┌─────────────────┐
+ │ ││ [0] │ ... │ [445] ││ │
+ │before valid range│├──────────┴──────────┴────────────┤│after valid range│
+ │ ││string literal (type: 'char[446]')││ │
+ └──────────────────┘└──────────────────────────────────┘└─────────────────┘
+ ├────────┬─────────┤├────────────────┬─────────────────┤├────────┬────────┤
+ │ │ │
+ ╭────────┴──────────────╮ ╭───────┴───────╮ ╭───────────┴───────────╮
+ │under-read of 100 bytes│ │size: 446 bytes│ │over-read of 3550 bytes│
+ ╰───────────────────────╯ ╰───────────────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 4096 bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │
+ │ │ │ │ │
+ v v v v v
+ ┌──────────────────┐┌───────┬───────┬─────────┐┌───────────────────────┐
+ │ ││ [0] │ ... │ [99] ││ │
+ │before valid range│├───────┴───────┴─────────┤│ after valid range │
+ │ ││'buf' (type: 'char[100]')││ │
+ └──────────────────┘└─────────────────────────┘└───────────────────────┘
+ ├────────┬─────────┤├────────────┬────────────┤├───────────┬───────────┤
+ │ │ │
+ │ ╭─────────┴─────────╮ ╭───────────┴──────────╮
+ │ │capacity: 100 bytes│ │overflow of 3946 bytes│
+ │ ╰───────────────────╯ ╰──────────────────────╯
+ ╭────────┴─────────────╮
+ │underwrite of 50 bytes│
+ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The read and write diagrams are each emitted twice: once for the "before"
+ and once for the "after" diagnostic. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ read of 4096 bytes │
+ └─────────────────────────────────────────────────────────────────────────┘
+ ^ ^ ^ ^ ^
+ │ │ │ │ │
+ │ │ │ │ │
+ ┌──────────────────┐┌──────────┬──────────┬────────────┐┌─────────────────┐
+ │ ││ [0] │ ... │ [445] ││ │
+ │before valid range│├──────────┴──────────┴────────────┤│after valid range│
+ │ ││string literal (type: 'char[446]')││ │
+ └──────────────────┘└──────────────────────────────────┘└─────────────────┘
+ ├────────┬─────────┤├────────────────┬─────────────────┤├────────┬────────┤
+ │ │ │
+ ╭────────┴──────────────╮ ╭───────┴───────╮ ╭───────────┴───────────╮
+ │under-read of 100 bytes│ │size: 446 bytes│ │over-read of 3550 bytes│
+ ╰───────────────────────╯ ╰───────────────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 4096 bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │
+ │ │ │ │ │
+ v v v v v
+ ┌──────────────────┐┌───────┬───────┬─────────┐┌───────────────────────┐
+ │ ││ [0] │ ... │ [99] ││ │
+ │before valid range│├───────┴───────┴─────────┤│ after valid range │
+ │ ││'buf' (type: 'char[100]')││ │
+ └──────────────────┘└─────────────────────────┘└───────────────────────┘
+ ├────────┬─────────┤├────────────┬────────────┤├───────────┬───────────┤
+ │ │ │
+ │ ╭─────────┴─────────╮ ╭───────────┴──────────╮
+ │ │capacity: 100 bytes│ │overflow of 3946 bytes│
+ │ ╰───────────────────╯ ╰──────────────────────╯
+ ╭────────┴─────────────╮
+ │underwrite of 50 bytes│
+ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c
new file mode 100644
index 0000000..25a9acc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c
@@ -0,0 +1,36 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_string_with_control_chars ()
+{
+ char buf[8];
+ strcpy (buf, "\tone\n\ttwo\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 11 bytes into a region of size 8 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬─────┬─────┬─────┬─────┬─────┐┌─────┬─────┬──────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │ [6] │ [7] ││ [8] │ [9] │ [10] │
+ ├──────┼──────┼──────┼─────┼─────┼─────┼─────┼─────┤├─────┼─────┼──────┤
+ │ 0x09 │ 'o' │ 'n' │ 'e' │0x0a │0x09 │ 't' │ 'w' ││ 'o' │0x0a │ NUL │
+ ├──────┴──────┴──────┴─────┴─────┴─────┴─────┴─────┴┴─────┴─────┴──────┤
+ │ string literal (type: 'char[11]') │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v v
+ ┌──────┬─────────────────────────────────────┬─────┐┌──────────────────┐
+ │ [0] │ ... │ [7] ││ │
+ ├──────┴─────────────────────────────────────┴─────┤│after valid range │
+ │ 'buf' (type: 'char[8]') ││ │
+ └──────────────────────────────────────────────────┘└──────────────────┘
+ ├────────────────────────┬─────────────────────────┤├────────┬─────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 8 bytes│ │overflow of 3 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c
new file mode 100644
index 0000000..24d8735
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c
@@ -0,0 +1,34 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/* Gap of 4, then an overflow of 4. */
+
+void test2 (size_t size)
+{
+ int32_t *buf = __builtin_malloc (size * sizeof(int32_t)); /* { dg-message "\\(1\\) capacity: 'size \\* 4' bytes" } */
+ if (!buf) return;
+
+ buf[size + 1] = 42; /* { dg-warning "heap-based buffer overflow" } */
+ __builtin_free (buf);
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────┐
+ │write of '(int) 42'│
+ └───────────────────┘
+ │
+ │
+ v
+ ┌───────────────────────────────┐ ┌───────────────────┐
+ │buffer allocated on heap at (1)│ │ after valid range │
+ └───────────────────────────────┘ └───────────────────┘
+ ├───────────────┬───────────────┤├───────┬────────┤├─────────┬─────────┤
+ │ │ │
+ ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮
+ │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│
+ ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c
new file mode 100644
index 0000000..bb9ad66
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c
@@ -0,0 +1,42 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#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 } */
+}
+
+// TODO: show index of accessed element
+// TODO: show field of accessed element
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────────────┐
+ │read of 'int32_t' (4 bytes)│
+ └───────────────────────────┘
+ ^
+ │
+ │
+ ┌───────────────────────────┐ ┌─────────┬─────────┬─────────┐
+ │ │ │ [0] │ ... │ [9] │
+ │ before valid range │ ├─────────┴─────────┴─────────┤
+ │ │ │'arr' (type: 'struct st[10]')│
+ └───────────────────────────┘ └─────────────────────────────┘
+ ├─────────────┬─────────────┤├────┬─────┤├──────────────┬──────────────┤
+ │ │ │
+ ╭──────────┴──────────╮ ╭─────┴────╮ ╭───────┴───────╮
+ │under-read of 4 bytes│ │2380 bytes│ │size: 240 bytes│
+ ╰─────────────────────╯ ╰──────────╯ ╰───────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
index 7c8d1b3..5b8ff7b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
@@ -26,7 +26,7 @@ void test_2 (void *p, void *q)
foo(p);
/* { dg-warning "pattern match on 'p != 0'" "p != 0" { target *-*-* } cond_2 } */
- /* { dg-warning "pattern match on 'tmp1 | tmp2 != 0'" "tmp1 | tmp2 != 0" { target *-*-* } cond_2 } */
+ /* { dg-warning "pattern match on 'p == 0 | q == 0 != 0'" "tmp1 | tmp2 != 0" { target *-*-* } cond_2 } */
/* { dg-warning "pattern match on 'q != 0'" "q != 0" { target *-*-* } cond_2 } */
}
@@ -42,6 +42,6 @@ void test_3 (void *p, void *q)
foo(p);
/* { dg-warning "pattern match on 'p == 0'" "p == 0" { target *-*-* } cond_3 } */
- /* { dg-warning "pattern match on 'tmp1 & tmp2 == 0'" "tmp1 & tmp2 == 0" { target *-*-* } cond_3 } */
+ /* { dg-warning "pattern match on 'p == 0 & q == 0 == 0'" "tmp1 & tmp2 == 0" { target *-*-* } cond_3 } */
/* { dg-warning "pattern match on 'q == 0'" "q == 0" { target *-*-* } cond_3 } */
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101962.c b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
index b878aad..5eb7cf0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101962.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
@@ -16,7 +16,7 @@ maybe_inc_int_ptr (int *ptr)
int
test_1 (void)
{
- int stack; /* { dg-message "region created on stack here" } */
+ int stack;
int *a = &stack;
a = maybe_inc_int_ptr (a);
a = maybe_inc_int_ptr (a);