This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Bounds checking for TREE_VEC_ELT and related bugs (PR c++/8511)


This patch adds bounds checking (under --enable-checking=tree) to
TREE_VEC_ELT.  Bootstrap exposed a few bugs, which are corrected.
There are no regressions in the testsuite.

This *should* resolve PR c++/8511; however, I am not certain of the
fix to that part of the code (the changes to cp/pt.c).  I would
appreciate a once-over by C++ maintainers.

Note that tree_vec_elt_check_failed adds one to the index, because it
was too damn confusing seeing 'accessed elt 2 of tree_vec with 2 elts'
and having to remember that elt 2 is the third one.

zw

        * tree.c (tree_vec_elt_check_failed): New function.
        * tree.h (TREE_VEC_ELT_CHECK): New checking macro.
        (TREE_VEC_ELT): Use it.

        * tree-inline.c (optimize_inline_calls): Don't copy a
        zero-length vector.
cp:
        * pt.c (tsubst): Do not access TMPL_ARG with idx out of range.
        * search.c (dfs_push_decls): Do not try to reorder elements
        3..n of method_vec if method_vec has only two elements.
        Reverse order of two tests to avoid accessing unallocated
        memory.

===================================================================
Index: tree.c
--- tree.c	23 Oct 2002 17:13:15 -0000	1.278
+++ tree.c	14 Nov 2002 19:54:47 -0000
@@ -4665,6 +4665,22 @@ tree_class_check_failed (node, cl, file,
      tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
 }
 
+/* Similar to above, except that the check is for the bounds of a TREE_VEC's
+   (dynamically sized) vector.  */
+
+void
+tree_vec_elt_check_failed (idx, len, file, line, function)
+     int idx;
+     int len;
+     const char *file;
+     int line;
+     const char *function;
+{
+  internal_error
+    ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
+     idx + 1, len, function, trim_filename (file), line);
+}
+
 #endif /* ENABLE_TREE_CHECKING */
 
 /* For a new vector type node T, build the information necessary for
===================================================================
Index: tree.h
--- tree.h	23 Oct 2002 17:13:15 -0000	1.360
+++ tree.h	14 Nov 2002 19:54:48 -0000
@@ -317,12 +317,26 @@ struct tree_common GTY(())
 			       __FUNCTION__);				\
     __t; })
 
+#define TREE_VEC_ELT_CHECK(t, i) __extension__				\
+(*({const tree __t = t;							\
+    const int __i = (i);						\
+    if (TREE_CODE (__t) != TREE_VEC)					\
+      tree_check_failed (__t, TREE_VEC,					\
+			 __FILE__, __LINE__, __FUNCTION__);		\
+    if (__i < 0 || __i >= __t->vec.length)				\
+      tree_vec_elt_check_failed (__i, __t->vec.length,			\
+				 __FILE__, __LINE__, __FUNCTION__);	\
+    &__t->vec.a[__i]; }))
+
 extern void tree_check_failed PARAMS ((const tree, enum tree_code,
 				       const char *, int, const char *))
     ATTRIBUTE_NORETURN;
 extern void tree_class_check_failed PARAMS ((const tree, int,
 					     const char *, int, const char *))
     ATTRIBUTE_NORETURN;
+extern void tree_vec_elt_check_failed PARAMS ((int, int, const char *,
+					       int, const char *))
+    ATTRIBUTE_NORETURN;
 
 #else /* not ENABLE_TREE_CHECKING, or not gcc */
 
@@ -330,6 +344,7 @@ extern void tree_class_check_failed PARA
 #define TREE_CLASS_CHECK(t, code)	(t)
 #define CST_OR_CONSTRUCTOR_CHECK(t)	(t)
 #define EXPR_CHECK(t)			(t)
+#define TREE_VEC_ELT_CHECK(t, i)	((t)->vec.a[i])
 
 #endif
 
@@ -810,9 +825,10 @@ struct tree_list GTY(())
 
 /* In a TREE_VEC node.  */
 #define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->vec.length)
-#define TREE_VEC_ELT(NODE,I) (TREE_VEC_CHECK (NODE)->vec.a[I])
 #define TREE_VEC_END(NODE) \
   ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->vec.length]))
+
+#define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I)
 
 struct tree_vec GTY(())
 {
===================================================================
Index: tree-inline.c
--- tree-inline.c	25 Oct 2002 17:26:51 -0000	1.34
+++ tree-inline.c	14 Nov 2002 19:54:46 -0000
@@ -1367,8 +1367,9 @@ optimize_inline_calls (fn)
     {
       tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns));
 
-      memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
-	      VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
+      if (VARRAY_ACTIVE_SIZE (id.inlined_fns))
+	memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
+		VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
       DECL_INLINED_FNS (fn) = ifn;
     }
 }
===================================================================
Index: cp/pt.c
--- cp/pt.c	9 Nov 2002 11:53:16 -0000	1.630
+++ cp/pt.c	14 Nov 2002 19:54:51 -0000
@@ -6539,7 +6539,8 @@ tsubst (t, args, complain, in_decl)
 	    tree arg = NULL_TREE;
 
 	    levels = TMPL_ARGS_DEPTH (args);
-	    if (level <= levels)
+	    if (level <= levels
+		&& idx < NUM_TMPL_ARGS (TMPL_ARGS_LEVEL (args, level)))
 	      arg = TMPL_ARG (args, level, idx);
 
 	    if (arg == error_mark_node)
===================================================================
Index: cp/search.c
--- cp/search.c	4 Nov 2002 01:45:55 -0000	1.240
+++ cp/search.c	14 Nov 2002 19:54:51 -0000
@@ -2544,7 +2544,8 @@ dfs_push_decls (binfo, data)
 	  
       method_vec = (CLASS_TYPE_P (type) 
 		    ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
-      if (method_vec)
+
+      if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
 	{
 	  tree *methods;
 	  tree *end;
@@ -2553,7 +2554,7 @@ dfs_push_decls (binfo, data)
 	  end = TREE_VEC_END (method_vec);
 
 	  for (methods = &TREE_VEC_ELT (method_vec, 2);
-	       *methods && methods != end;
+	       methods < end && *methods;
 	       methods++)
 	    setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)), 
 				  /*type_binding_p=*/0);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]