aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-03-14 15:30:43 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-03-14 15:30:43 +0100
commit7f476ee30bab3976eefc3226481e617add83401a (patch)
tree0390818a16442b72a8e24ba1d0a64a75a193c9eb /gcc
parent5abe571e0276fafcc6eed27c27abb28943e67c6f (diff)
downloadgcc-7f476ee30bab3976eefc3226481e617add83401a.zip
gcc-7f476ee30bab3976eefc3226481e617add83401a.tar.gz
gcc-7f476ee30bab3976eefc3226481e617add83401a.tar.bz2
analyzer: Fix ICE in cmp_csts_same_type on RAW_DATA_CST [PR119278]
The following testcase ICEs in cmp_csts_same_type because RAW_DATA_CST isn't handled there. As TREE_TYPE (cst1) in that case is INTEGER_TYPE, e.g. char/signed char/unsigned char, the type itself doesn't imply the size, so the length is compared first, followed by comparing the data. While at it, I've noticed STRING_CST handling is wrong, because STRING_CST can represent even string literals with embedded nul characters. We shouldn't stop at those, hence memcmp. While for STRING_CST TREE_TYPE should likely already imply the length and so same type should imply same TREE_STRING_LENGTH, I've repeated the comparisons in there just in case. 2025-03-14 Jakub Jelinek <jakub@redhat.com> PR analyzer/119278 * svalue.cc (cmp_csts_same_type): For STRING_CST, compare TREE_STRING_LENGTH first just in case and use memcmp rather than strcmp. Handle RAW_DATA_CST. * c-c++-common/analyzer/pr119278.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/svalue.cc17
-rw-r--r--gcc/testsuite/c-c++-common/analyzer/pr119278.c20
2 files changed, 35 insertions, 2 deletions
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index c61be4d..2e3f051 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -467,8 +467,21 @@ cmp_csts_same_type (const_tree cst1, const_tree cst2)
case INTEGER_CST:
return tree_int_cst_compare (cst1, cst2);
case STRING_CST:
- return strcmp (TREE_STRING_POINTER (cst1),
- TREE_STRING_POINTER (cst2));
+ if (TREE_STRING_LENGTH (cst1) < TREE_STRING_LENGTH (cst2))
+ return -1;
+ if (TREE_STRING_LENGTH (cst1) > TREE_STRING_LENGTH (cst2))
+ return 1;
+ return memcmp (TREE_STRING_POINTER (cst1),
+ TREE_STRING_POINTER (cst2),
+ TREE_STRING_LENGTH (cst1));
+ case RAW_DATA_CST:
+ if (RAW_DATA_LENGTH (cst1) < RAW_DATA_LENGTH (cst2))
+ return -1;
+ if (RAW_DATA_LENGTH (cst1) > RAW_DATA_LENGTH (cst2))
+ return 1;
+ return memcmp (RAW_DATA_POINTER (cst1),
+ RAW_DATA_POINTER (cst2),
+ RAW_DATA_LENGTH (cst1));
case REAL_CST:
/* Impose an arbitrary but deterministic order. */
return memcmp (TREE_REAL_CST_PTR (cst1),
diff --git a/gcc/testsuite/c-c++-common/analyzer/pr119278.c b/gcc/testsuite/c-c++-common/analyzer/pr119278.c
new file mode 100644
index 0000000..bb1dcb6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/pr119278.c
@@ -0,0 +1,20 @@
+/* PR analyzer/119278 */
+/* { dg-do compile } */
+
+const unsigned char a[] = {
+#define A 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
+ A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A
+};
+const unsigned char b[] = {
+#define B 16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1
+ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B
+};
+struct S { const unsigned char *s; };
+void bar (struct S *);
+
+void
+foo (void)
+{
+ struct S t[] = { a, b };
+ bar (t);
+}