This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Bounds checking for TREE_VEC_ELT and related bugs (PR c++/8511)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org, mark at codesourcery dot com
- Date: Thu, 14 Nov 2002 12:01:43 -0800
- Subject: 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);