aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-08-25 08:41:19 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2023-08-25 08:41:19 -0400
commit99a3fcb8ff0bf27407c525415384372189e2c3cc (patch)
tree9b2e2f6ad08def30ba6db712e6c2b3e09e6231ef /gcc
parent845ee9c7107956845e487cb123fa581d9c70ea1b (diff)
downloadgcc-99a3fcb8ff0bf27407c525415384372189e2c3cc.zip
gcc-99a3fcb8ff0bf27407c525415384372189e2c3cc.tar.gz
gcc-99a3fcb8ff0bf27407c525415384372189e2c3cc.tar.bz2
analyzer: fix ICE in text art strings support
gcc/analyzer/ChangeLog: * access-diagram.cc (class string_region_spatial_item): Remove assumption that the string is written to the start of the cluster. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/out-of-bounds-diagram-17.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-18.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-19.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/access-diagram.cc57
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-17.c34
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-18.c38
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c45
4 files changed, 155 insertions, 19 deletions
diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc
index d7b669a..a51d594 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 0000000..6920e8c
--- /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 0000000..ea0b880
--- /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 0000000..35ab72b
--- /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 "" } */