nana: undefined behaviour - many violations of strict aliasing
All of these reinterpret_casts are undefined behaviour:
owner and parent arguments are of type window which is:
which is:
The other side of casts is basic_window which is
which is a separate class that does not share any ancestors in it’s inheritance tree with detail::window_handle_impl
Therefore, the dereference of pointers coming from casts between detail::window_handle_impl* and basic_window* is undefined behaviour.
This issue is probably related to #445 because:
- the intialization path practically always goes through this code (in order to create a window)
- the code does not crash without link-time optimization (used
-flto -fno-fat-lto-objects) (this suggests that crucial violations are probably across source-file/function boundary) - some minimal examples do not crash when compiled with
-fno-strict-aliasing
Other notes:
- there are many more suspicious
reinterpret_casts in the repository, all of them should be checked; total 684 casts in the project as reported bygrep -r reinterpret_cast - compilers can not validate strict aliasing at compile time, in majority of non-trivial cases there are no warnings
- GCC 8.3 with
-Wstrict-aliasing=2or-Wstict-aliasing=1on this project catches only a small number of only possible strict aliasing violations
nana\source\system\dataexch.cpp:73:72: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
if (::GetDIBits(hDC, (HBITMAP)g.pixmap(), 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS) == 0) {
^~~~
nana\source\paint\graphics.cpp: In member function 'void nana::paint::graphics::make(const nana::size&)':
nana\source\paint\graphics.cpp:349:90: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(dw->pixbuf_ptr)), 0, 0);
^~~~~~~~~~~~~~~~~
nana\source\paint\graphics.cpp: In member function 'void nana::paint::graphics::save_as_file(const char*) const':
nana\source\paint\graphics.cpp:1079:98: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
HBITMAP hBmp = ::CreateDIBSection(hdcMem, &bmpInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&pData), 0, 0);
^~~~~~
This is guuaranteed to crash given powerful enough optimizer (the last line violates both type aliasing rules and type alignment requirements):
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 1
- Comments: 26 (13 by maintainers)
Links to this issue
Commits related to this issue
- refactor types(#450) — committed to cnjinhao/nana by cnjinhao 5 years ago
- refactor types(#450) — committed to Xeverous/nana by cnjinhao 5 years ago
waiting…
Hi @Xeverous , still wating for your ideas about how to make the code better…
It is complete. These are not forward declarations:
https://github.com/cnjinhao/nana/blob/ffa170b5f560dbf899030bdeb0e539aa95b03649/include/nana/gui/basis.hpp#L25-L31
Note that the completeness has no meaning for strict aliasing.
My typo in previous comment - alignment not of pointers but of pointed types should be compared. So
alignof(basic_window) <= alignof(detail::native_window_impl)It is not, even more - you can not query the alignment of an incomplete type.
Right now you are trying to defend the current implementation. Please stop it. There is no place for
reinterpret_casts outside dealing with bit representation (ie when reading encoded file formats) or reading raw memory for debug purposes. Object-oriented code that relies on reinterpretation casts will be broken. It would be much better to think how to refactor and correctly hide the API using forward declarations ordetailnamespace. C++ type system exists for a reason, don’t try to defend code that breaks it.