analyzer: fix ICE with -fsanitize=undefined [PR98293]
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 5 Jan 2021 00:20:32 +0000 (19:20 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 5 Jan 2021 00:20:32 +0000 (19:20 -0500)
-fsanitize=undefined with calls to nonnull functions
creates struct __ubsan_nonnull_arg_data instances
with CONSTRUCTORs for RECORD_TYPEs with NULL index values.
The analyzer was mistakenly using INTEGER_CST for these
fields, leading to ICEs.

Fix the issue by iterating through the fields in the type
for such cases, imitating similar logic in varasm.c's
output_constructor.

gcc/analyzer/ChangeLog:
PR analyzer/98293
* store.cc (binding_map::apply_ctor_to_region): When "index" is
NULL, iterate through the fields for RECORD_TYPEs, rather than
creating an INTEGER_CST index.

gcc/testsuite/ChangeLog:
PR analyzer/98293
* gcc.dg/analyzer/pr98293.c: New test.

gcc/analyzer/store.cc
gcc/testsuite/gcc.dg/analyzer/pr98293.c [new file with mode: 0644]

index 35a7e2985cdebb71776a837efd23dfb607b08a7e..b4a4d5f3bb2ae081c4e10da70162fcd478326cf9 100644 (file)
@@ -524,10 +524,27 @@ binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
   unsigned ix;
   tree index;
   tree val;
+  tree parent_type = parent_reg->get_type ();
+  tree field;
+  if (TREE_CODE (parent_type) == RECORD_TYPE)
+    field = TYPE_FIELDS (parent_type);
+  else
+    field = NULL_TREE;
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, index, val)
     {
       if (!index)
-       index = build_int_cst (integer_type_node, ix);
+       {
+         /* If index is NULL, then iterate through the fields for
+            a RECORD_TYPE, or use an INTEGER_CST otherwise.
+            Compare with similar logic in output_constructor.  */
+         if (field)
+           {
+             index = field;
+             field = DECL_CHAIN (field);
+           }
+         else
+           index = build_int_cst (integer_type_node, ix);
+       }
       else if (TREE_CODE (index) == RANGE_EXPR)
        {
          tree min_index = TREE_OPERAND (index, 0);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr98293.c b/gcc/testsuite/gcc.dg/analyzer/pr98293.c
new file mode 100644 (file)
index 0000000..f750c90
--- /dev/null
@@ -0,0 +1,2 @@
+/* { dg-additional-options "-fsanitize=undefined" } */
+#include "../pr93399.c"