Can a field of anonymous union reference itself during the constexpr evaluation?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Can a field of anonymous union reference itself during the constexpr evaluation?

Artem Dergachev via cfe-dev
Hello all,

I was investigating the bug Heap-use-after-free in clang::APValue::swap which corresponds to the more human-friendly form

struct S {
  union {
    int i = i = 3;
  };
  constexpr S() {}
};
static_assert(S().i == 3, "”);

When you compile this example with
clang -std=c++14 -fsyntax-only

it crashes Clang 5.0.0, 4.0.0, 3.9.0 and running with ASAN shows there is use after free in APValue hierarchy caused by the `i` on the right hand side. If anybody is interested I can provide more details about the mechanism of the crash but it’s not important for the question I have.

Should Clang accept such code at all according to C++14 constexpr evaluation rules? GCC 7.2 rejects it, Clang ToT with -std=c++11 rejects it too. Also it would be helpful to shed some light on the differences between C++11 and C++14 for this example as for `int i = i;` and -std=c++11 Clang hits the assertion
Assertion failed: (isInt() && "Invalid accessor"), function getInt, file clang/include/clang/AST/APValue.h, line 202.

Thanks,
Volodymyr

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Can a field of anonymous union reference itself during the constexpr evaluation?

Artem Dergachev via cfe-dev
On 1/18/2018 6:54 PM, Volodymyr Sapsai via cfe-dev wrote:
Hello all,

I was investigating the bug Heap-use-after-free in clang::APValue::swap which corresponds to the more human-friendly form

struct S {
  union {
    int i = i = 3;
  };
  constexpr S() {}
};
static_assert(S().i == 3, "”);

When you compile this example with
clang -std=c++14 -fsyntax-only

it crashes Clang 5.0.0, 4.0.0, 3.9.0 and running with ASAN shows there is use after free in APValue hierarchy caused by the `i` on the right hand side. If anybody is interested I can provide more details about the mechanism of the crash but it’s not important for the question I have.

Should Clang accept such code at all according to C++14 constexpr evaluation rules? GCC 7.2 rejects it, Clang ToT with -std=c++11 rejects it too. Also it would be helpful to shed some light on the differences between C++11 and C++14 for this example as for `int i = i;` and -std=c++11 Clang hits the assertion

The constexpr evaluation rules got substantially rewritten for C++14 (assignment wasn't allowed at all in C++11).

Let's work through some cases.  Consider the following:

struct S {
  int i = 2;
  int j = i = 3;
  constexpr S() {}
};
static_assert(S().i == 3, "");

Both clang and gcc accept this because assignment is generally allowed in constant expressions.

How about the following?

struct S {
  int i = i = 3;
  constexpr S() {}
};
static_assert(S().i == 3, "");

The relevant standard text is that constant evaluation doesn't allow "modification of an object (8.5.18, 8.5.1.6, 8.5.2.2) unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e".  gcc accepts this, clang rejects it because it thinks the lifetime of i doesn't start until after it's initialized.  clang's interpretation seems reasonable.

Then we come to your testcase, with the anonymous union.  I don't think the addition of the anonymous union changes the analysis in any significant way.

-Eli
-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Can a field of anonymous union reference itself during the constexpr evaluation?

Artem Dergachev via cfe-dev
On Jan 18, 2018, at 19:28, Friedman, Eli <[hidden email]> wrote:

On 1/18/2018 6:54 PM, Volodymyr Sapsai via cfe-dev wrote:
Hello all,

I was investigating the bug Heap-use-after-free in clang::APValue::swap which corresponds to the more human-friendly form

struct S {
  union {
    int i = i = 3;
  };
  constexpr S() {}
};
static_assert(S().i == 3, "”);

When you compile this example with
clang -std=c++14 -fsyntax-only

it crashes Clang 5.0.0, 4.0.0, 3.9.0 and running with ASAN shows there is use after free in APValue hierarchy caused by the `i` on the right hand side. If anybody is interested I can provide more details about the mechanism of the crash but it’s not important for the question I have.

Should Clang accept such code at all according to C++14 constexpr evaluation rules? GCC 7.2 rejects it, Clang ToT with -std=c++11 rejects it too. Also it would be helpful to shed some light on the differences between C++11 and C++14 for this example as for `int i = i;` and -std=c++11 Clang hits the assertion

The constexpr evaluation rules got substantially rewritten for C++14 (assignment wasn't allowed at all in C++11).

Let's work through some cases.  Consider the following:

struct S {
  int i = 2;
  int j = i = 3;
  constexpr S() {}
};
static_assert(S().i == 3, "");

Both clang and gcc accept this because assignment is generally allowed in constant expressions.

How about the following?

struct S {
  int i = i = 3;
  constexpr S() {}
};
static_assert(S().i == 3, "");

The relevant standard text is that constant evaluation doesn't allow "modification of an object (8.5.18, 8.5.1.6, 8.5.2.2) unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e".  gcc accepts this, clang rejects it because it thinks the lifetime of i doesn't start until after it's initialized.  clang's interpretation seems reasonable.

Then we come to your testcase, with the anonymous union.  I don't think the addition of the anonymous union changes the analysis in any significant way.

-Eli
-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Thank you, Eli. Lifetime explanation is useful and helps to grasp the difference between GCC and Clang.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev