]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Avoid pathological function redeclarations when checking access sizes [PR102759].
authorMartin Sebor <msebor@redhat.com>
Wed, 17 Nov 2021 22:09:23 +0000 (15:09 -0700)
committerMartin Sebor <msebor@redhat.com>
Wed, 17 Nov 2021 22:09:23 +0000 (15:09 -0700)
Resolves:
PR tree-optimization/102759 - ICE: Segmentation fault in maybe_check_access_sizes since r12-2976-gb48d4e6818674898

gcc/ChangeLog:

PR tree-optimization/102759
* gimple-array-bounds.cc (build_printable_array_type): Move...
* gimple-ssa-warn-access.cc (build_printable_array_type): Avoid
pathological function redeclarations that remove a previously
declared prototype.
Improve formatting of function arguments in informational notes.
* pointer-query.cc (build_printable_array_type): ...to here.
* pointer-query.h (build_printable_array_type): Declared.

gcc/testsuite/ChangeLog:

PR tree-optimization/102759
* gcc.dg/Warray-parameter-10.c: New test.
* gcc.dg/Wstringop-overflow-82.c: New test.

gcc/gimple-array-bounds.cc
gcc/gimple-ssa-warn-access.cc
gcc/pointer-query.cc
gcc/pointer-query.h
gcc/testsuite/gcc.dg/Warray-parameter-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wstringop-overflow-82.c [new file with mode: 0644]

index a35355989981bd3f5068e81658f6d556427ee91b..ddb99d263d18d9a21f6d4319f8b4947a67e1610d 100644 (file)
@@ -372,31 +372,6 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
   return warned;
 }
 
-/* Wrapper around build_array_type_nelts that makes sure the array
-   can be created at all and handles zero sized arrays specially.  */
-
-static tree
-build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
-{
-  if (TYPE_SIZE_UNIT (eltype)
-      && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
-      && !integer_zerop (TYPE_SIZE_UNIT (eltype))
-      && TYPE_ALIGN_UNIT (eltype) > 1
-      && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
-                  ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
-    eltype = TYPE_MAIN_VARIANT (eltype);
-
-  if (nelts)
-    return build_array_type_nelts (eltype, nelts);
-
-  tree idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
-  tree arrtype = build_array_type (eltype, idxtype);
-  arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
-  TYPE_SIZE (arrtype) = bitsize_zero_node;
-  TYPE_SIZE_UNIT (arrtype) = size_zero_node;
-  return arrtype;
-}
-
 /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
    references to string constants.  If VRP can determine that the array
    subscript is a constant, check if it is outside valid range.
index 22c791d833a0b9b5415bb3ea21ff7e6a21e06625..48bf8aaff50af5523034786107cd15c083f18c3b 100644 (file)
@@ -2978,10 +2978,16 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
        continue;
 
       tree ptrtype = fntype_argno_type (fntype, ptridx);
+      if (!ptrtype)
+       /* A function with a prototype was redeclared without one and
+          the protype has been lost.  See pr102759.  Avoid dealing
+          with this pathological case.  */
+       return;
+
       tree argtype = TREE_TYPE (ptrtype);
 
-      /* The size of the access by the call.  */
-      tree access_size;
+      /* The size of the access by the call in elements.  */
+      tree access_nelts;
       if (sizidx == -1)
        {
          /* If only the pointer attribute operand was specified and
@@ -2991,17 +2997,17 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
             if the pointer is also declared with attribute nonnull.  */
          if (access.second.minsize
              && access.second.minsize != HOST_WIDE_INT_M1U)
-           access_size = build_int_cstu (sizetype, access.second.minsize);
+           access_nelts = build_int_cstu (sizetype, access.second.minsize);
          else
-           access_size = size_one_node;
+           access_nelts = size_one_node;
        }
       else
-       access_size = rwm->get (sizidx)->size;
+       access_nelts = rwm->get (sizidx)->size;
 
       /* Format the value or range to avoid an explosion of messages.  */
       char sizstr[80];
       tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
-      if (get_size_range (m_ptr_qry.rvals, access_size, stmt, sizrng, 1))
+      if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1))
        {
          char *s0 = print_generic_expr_to_str (sizrng[0]);
          if (tree_int_cst_equal (sizrng[0], sizrng[1]))
@@ -3059,6 +3065,8 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
            }
        }
 
+      /* The size of the access by the call in bytes.  */
+      tree access_size = NULL_TREE;
       if (tree_int_cst_sgn (sizrng[0]) >= 0)
        {
          if (COMPLETE_TYPE_P (argtype))
@@ -3075,9 +3083,9 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
                    access_size = wide_int_to_tree (sizetype, minsize);
                  }
            }
+         else
+           access_size = access_nelts;
        }
-      else
-       access_size = NULL_TREE;
 
       if (integer_zerop (ptr))
        {
@@ -3172,8 +3180,13 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
       if (opt_warned != no_warning)
        {
          if (access.second.internal_p)
-           inform (loc, "referencing argument %u of type %qT",
-                   ptridx + 1, ptrtype);
+           {
+             unsigned HOST_WIDE_INT nelts =
+               access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U;
+             tree arrtype = build_printable_array_type (argtype, nelts);
+             inform (loc, "referencing argument %u of type %qT",
+                     ptridx + 1, arrtype);
+           }
          else
            /* If check_access issued a warning above, append the relevant
               attribute to the string.  */
index a0e4543d8a3e86575d01ced95afc64ebc73130c9..2ead027161753ec32f20a50f5a2fb7c678e669f4 100644 (file)
@@ -2358,3 +2358,33 @@ array_elt_at_offset (tree artype, HOST_WIDE_INT off,
 
   return NULL_TREE;
 }
+
+/* Wrapper around build_array_type_nelts that makes sure the array
+   can be created at all and handles zero sized arrays specially.  */
+
+tree
+build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
+{
+  if (TYPE_SIZE_UNIT (eltype)
+      && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
+      && !integer_zerop (TYPE_SIZE_UNIT (eltype))
+      && TYPE_ALIGN_UNIT (eltype) > 1
+      && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
+                  ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
+    eltype = TYPE_MAIN_VARIANT (eltype);
+
+  /* Consider excessive NELTS an array of unknown bound.  */
+  tree idxtype = NULL_TREE;
+  if (nelts < HOST_WIDE_INT_MAX)
+    {
+      if (nelts)
+       return build_array_type_nelts (eltype, nelts);
+      idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+    }
+
+  tree arrtype = build_array_type (eltype, idxtype);
+  arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
+  TYPE_SIZE (arrtype) = bitsize_zero_node;
+  TYPE_SIZE_UNIT (arrtype) = size_zero_node;
+  return arrtype;
+}
index c8215b681ef859442847af3d0a4d8408ebf070af..fbea3316f14d3bd8ed28e2b8863832327dc89334 100644 (file)
@@ -275,4 +275,7 @@ extern tree array_elt_at_offset (tree, HOST_WIDE_INT,
                                 HOST_WIDE_INT * = nullptr,
                                 HOST_WIDE_INT * = nullptr);
 
+/* Helper to build an array type that can be printed.  */
+extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT);
+
 #endif   // GCC_POINTER_QUERY_H
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-10.c b/gcc/testsuite/gcc.dg/Warray-parameter-10.c
new file mode 100644 (file)
index 0000000..378f8af
--- /dev/null
@@ -0,0 +1,20 @@
+/* PR c/102759 - ICE calling a function taking an argument redeclared
+   without a prototype.
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+void f (void)
+{
+  void gia (int[2]);
+  void g ();
+}
+
+/* Redeclaring the g(int[]) above without a prototype loses it.  */
+void gia ();
+void g (int[2]);
+
+void h (void )
+{
+  gia (gia);
+  gia (g);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c
new file mode 100644 (file)
index 0000000..ee2693d
--- /dev/null
@@ -0,0 +1,29 @@
+/* Verify that notes after warnings for array and VLA parameters show
+   the array form.
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+void fia5 (int[5]);
+
+void gia3_fia5 (void)
+{
+  int a[3];
+  fia5 (a);             // { dg-warning "-Wstringop-overflow" }
+                        // { dg-message "argument 1 of type 'int\\\[5]'" "note" { target *-*-* } .-1 }
+}
+
+
+/* The type of the argument would ideall be 'int[n]' but the variable
+   bound is lost/cleared by free-lang-data and never makes it into
+   the middle end.  An (inferior) alternative would be 'int[*]' but
+   the pretty printer doesn't know how to format the star.  A better
+   solution might be to introduce a new notation, like 'int[$1]',
+   where the $1 refers to the VLA argument bound.  */
+void fvla (int n, int[n]);
+
+void gia3_fvla (void)
+{
+  int a[3];
+  fvla (sizeof a, a);   // { dg-warning "-Wstringop-overflow" }
+                        // { dg-message "argument 2 of type 'int\\\[]'" "note" { target *-*-* } .-1 }
+}