[cfe-dev] Can a field of anonymous union reference itself during the constexpr evaluation?

Volodymyr Sapsai via cfe-dev cfe-dev at lists.llvm.org
Fri Jan 19 12:54:43 PST 2018


On Jan 18, 2018, at 19:28, Friedman, Eli <efriedma at codeaurora.org> 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 <https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4985> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180119/e7dd7135/attachment.html>


More information about the cfe-dev mailing list