aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/constexpr.c11
-rw-r--r--gcc/testsuite/g++.dg/ubsan/vptr-18.C25
2 files changed, 35 insertions, 1 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 2ef6de8..b6f3e6e 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1998,11 +1998,20 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call,
to the object under construction or destruction, this object is
considered to be a most derived object that has the type of the
constructor or destructor's class. */
- tree vtable = build_vfield_ref (obj, TREE_TYPE (obj));
+ tree vtable = build_vfield_ref (obj, objtype);
vtable = cxx_eval_constant_expression (ctx, vtable, /*lval*/false,
non_constant_p, overflow_p);
if (*non_constant_p)
return call;
+ /* With -fsanitize=vptr, we initialize all vtable pointers to null,
+ so it's possible that we got a null pointer now. */
+ if (integer_zerop (vtable))
+ {
+ if (!ctx->quiet)
+ error_at (loc, "virtual table pointer is used uninitialized");
+ *non_constant_p = true;
+ return integer_zero_node;
+ }
/* VTABLE will be &_ZTV1A + 16 or similar, get _ZTV1A. */
vtable = extract_obj_from_addr_offset (vtable);
const tree mdtype = DECL_CONTEXT (vtable);
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-18.C b/gcc/testsuite/g++.dg/ubsan/vptr-18.C
new file mode 100644
index 0000000..cd2ca0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-18.C
@@ -0,0 +1,25 @@
+// PR c++/98103
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+// Modified constexpr-dynamic17.C.
+
+struct V {
+ virtual void f();
+};
+
+struct A : V { };
+
+struct B : V {
+ constexpr B(V*, A*);
+};
+
+struct D : B, A {
+ constexpr D() : B((A*)this, this) { }
+};
+
+constexpr B::B(V* v, A* a)
+{
+ dynamic_cast<B*>(a); // { dg-error "uninitialized" }
+}
+
+constexpr D d;