[llvm-bugs] [Bug 43585] New: Handling C++ exceptions on Windows x64 corrupts local variables

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Oct 7 03:06:47 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=43585

            Bug ID: 43585
           Summary: Handling C++ exceptions on Windows x64 corrupts local
                    variables
           Product: clang
           Version: 9.0
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: brian.apps at oxfordsemantic.tech
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org,
                    neeilans at live.com, richard-llvm at metafoo.co.uk

Created attachment 22638
  --> https://bugs.llvm.org/attachment.cgi?id=22638&action=edit
x64 Disassembly

I see segmentation faults in my product when switching from Clang 8 to Clang 9.
Sometimes local variables are incorrectly initialised after an exception has
been successfully caught. With certain input this can lead to a crash at a
later point. For one of our unit tests this crash is 100% repeatable.

After some investigation I'm confident this is a Windows only issue with
exception funclets incorrectly spilling XMM registers. I can confirm this issue
does not occur when I use the master branch of Clang because of the change
https://reviews.llvm.org/D66596 ([WinEH] Allocate space in funclets stack to
save XMM CSRs). This issue is a bit of showstopper for me because it leaves me
worried that there are similar problems in our product code that we have not
found through testing. I'm raising this issue in the hope of getting the D66596
change incorporated into a future clang 9 release.

It's hard to come up with a simple example. The code below demonstrates the
corruption problem (but not the crash). It shows how a constant data member is
initialised to the wrong value.

When the following code is compiled with:
clang-cl /O2 /Ob1 /EHsc code.cpp
and run it prints "This shouldn't happen to Two, value of a is 1". I would
expect the code to run without showing this message.

#include <iostream>

struct One {
    const size_t a = 1;
    const size_t b = 0;

    ~One() {
        if (a != 1)
            std::cout << "This shouldn't happen to One, value of a is " << a <<
"." << std::endl;
    }
};

struct Two {
    const size_t a = 2;
    const size_t b = 0;

    ~Two() {
        if (a != 2)
            std::cout << "This shouldn't happen to Two, value of a is " << a <<
"." << std::endl;
    }
};

void throwIt() {
    throw std::string();
}

bool mytest() {
    for (int i = 0; i < 2; ++i) {
        try {
            One one;
            throwIt();
        }
        catch (const std::string& s) {
            return true;
        }
    }
    return false;
}

int main(int argc, char* argv[]) {
    for (int i = 0; i < 2; ++i) {
        Two two;
        mytest();
    }
    return 0;
}


For more details see annotated attached disassembly it shows how mytest()
overwrites the CSR slot for XMM6 in both the unwinding and catch handling
funclets.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20191007/c5862201/attachment.html>


More information about the llvm-bugs mailing list