-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[CFI] update ignorelist to work with libstdc++ make_shared #118599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[CFI] update ignorelist to work with libstdc++ make_shared #118599
Conversation
2c53a65
to
9a9a538
Compare
It's also not clear that this one entry will work for a non-trivial C++ code base. Do you have more experience with using -fsanitize=cfi with libstdc++? |
Actually, there is already a bug reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96946. I have included this in the description.
To be honest, my team has been trying to enable CFI recently, and we encountered this issue just like others before. We have this problem with our non-trivial code base, and this patch can also fix the problem for us. |
I tried to comment on that GCC bug report page, but I don't have an account and I am working on getting my account setup. |
Is the correct fix really to just add an allow-list for individual cases of valid code? Doesn't that imply a problem with the sanitizer, or is that by design? This PR doesn't help this case, which fails using both -stdlib=libstdc++ and -stdlib=libc++, and is valid C++ as far as I can see: #include <new>
namespace x __attribute__((visibility("default")))
{
template<typename T>
struct buffer
{
alignas(__alignof__(T)) unsigned char buf[sizeof(T)];
void* addr() { return static_cast<void*>(buf); }
T* ptr() { return static_cast<T*>(addr()); }
};
}
struct IReporterFactory {
virtual ~IReporterFactory() = default;
};
class ReporterFactory : public IReporterFactory {};
int main()
{
auto p = new x::buffer<ReporterFactory>;
auto p2 = p->ptr(); // undefined here
::new(static_cast<void*>(p2)) ReporterFactory;
p->ptr()->~ReporterFactory();
delete p;
} And it doesn't help for this case which fails using -stdlib=libstdc++: #include <list>
struct IReporterFactory {
virtual ~IReporterFactory() = default;
};
class ReporterFactory : public IReporterFactory {};
int main()
{
std::list<ReporterFactory> l(1);
} (I plan to change the node-based containers in libstdc++ to use a union for the uninitialized storage, which should fix this case ... one day.) |
If you add a suppression for |
Here is the same problem for libc++: https://bugs.llvm.org/show_bug.cgi?id=48993, and it ends up adding The key problem about this kind of problem is (taken from the LLVM bugzilla) "CFI detects cast confusion bugs by checking that the vtable is correct for the type of the cast, but the vptr slot is still uninitialized.".
Do you want me to include those in this PR? |
That's for the relevant reviewers to decide, not me. But handling both |
I'm sorry, I am actually busy with other things right now. I will work on this patch later. |
Fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96946.
We had an old issue with libc++ in https://bugs.llvm.org/show_bug.cgi?id=48993, and it is fixed for libc++, but the same reproducer can still be reproduced with libstdc++(https://godbolt.org/z/n3EWvMKEP).
This patch adds an entry to deal with such cases.