https://gcc.gnu.org/g:7f476ee30bab3976eefc3226481e617add83401a
commit r15-8058-g7f476ee30bab3976eefc3226481e617add83401a Author: Jakub Jelinek <ja...@redhat.com> Date: Fri Mar 14 15:30:43 2025 +0100 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 <ja...@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. Diff: --- gcc/analyzer/svalue.cc | 17 +++++++++++++++-- gcc/testsuite/c-c++-common/analyzer/pr119278.c | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index c61be4d9002b..2e3f051d899c 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 000000000000..bb1dcb636d76 --- /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); +}