basil00 / WinDivert

WinDivert: Windows Packet Divert
https://reqrypt.org/windivert.html
Other
2.56k stars 513 forks source link

__out macro breaks <vector> in mingw STL #337

Open TsXor opened 1 year ago

TsXor commented 1 year ago

following snippet will not compile under mingw-w64

#include "windivert.h"
#include <vector>

int main(void) {
    std::vector<char> x = {1, 2, 3, 4};
}

mingw version:

Using built-in specs.
COLLECT_GCC=D:\chocolatey\lib\mingw\tools\install\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=D:/chocolatey/lib/mingw/tools/install/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/12.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-12.2.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64 --enable-host-shared --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev2, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/lib -L/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/lib -L/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/lib ' LD_FOR_TARGET=/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/bin/ld.exe --with-boot-ldflags=' -Wl,--disable-dynamicbase -static-libstdc++ -static-libgcc'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 12.2.0 (x86_64-posix-seh-rev2, Built by MinGW-W64 project)

compilation error:

正在启动生成...
g++.exe -std=c++23 -fdiagnostics-color=always -g E:\Users\23Xor\Desktop\winsock-redirect\extlibs\WinDivert\include\test.cpp -o E:\Users\23Xor\Desktop\winsock-redirect\extlibs\WinDivert\include\test.exe
In file included from D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_algobase.h:64,
                 from D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/vector:60,
                 from E:\Users\23Xor\Desktop\winsock-redirect\extlibs\WinDivert\include\test.cpp:2:
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h: In function 'constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(pair<_Tp1, _Tp2>&&)':
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h:861:52: error: no matching function for call to 'move()'
  861 |     { return __pair_get<_Int>::__move_get(std::move(__in)); }
      |                                           ~~~~~~~~~^~~~~~
In file included from D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h:61:
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/move.h:104:5: note: candidate: 'template<class _Tp> constexpr typename std::remove_reference<_Tp>::type&& std::move(_Tp&&)'
  104 |     move(_Tp&& __t) noexcept
      |     ^~~~
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/move.h:104:5: note:   template argument deduction/substitution failed:
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h:861:52: note:   candidate expects 1 argument, 0 provided
  861 |     { return __pair_get<_Int>::__move_get(std::move(__in)); }
      |                                           ~~~~~~~~~^~~~~~
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h: In function 'constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const pair<_Tp1, _Tp2>&&)':
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h:871:58: error: no matching function for call to 'move()'
  871 |     { return __pair_get<_Int>::__const_move_get(std::move(__in)); }
      |                                                 ~~~~~~~~~^~~~~~
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/move.h:104:5: note: candidate: 'template<class _Tp> constexpr typename std::remove_reference<_Tp>::type&& std::move(_Tp&&)'
  104 |     move(_Tp&& __t) noexcept
      |     ^~~~
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/move.h:104:5: note:   template argument deduction/substitution failed:
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_pair.h:871:58: note:   candidate expects 1 argument, 0 provided
  871 |     { return __pair_get<_Int>::__const_move_get(std::move(__in)); }
      |                                                 ~~~~~~~~~^~~~~~
In file included from D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/vector:63:
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_uninitialized.h: In function 'constexpr std::__enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*> std::__relocate_a_1(_Tp*, _Tp*, _Tp*, allocator<_T2>&)':
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_uninitialized.h:1113:21: error: expected primary-expression before '=' token
 1113 |               __out = std::__relocate_a_1(__first, __last, __out, __alloc);
      |                     ^
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_uninitialized.h:1113:65: error: expected primary-expression before ',' token
 1113 |               __out = std::__relocate_a_1(__first, __last, __out, __alloc);
      |                                                                 ^
D:/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/x86_64-w64-mingw32/12.2.0/include/c++/bits/stl_uninitialized.h:1114:27: error: expected primary-expression before '.' token
 1114 |               return __out.base();
      |                           ^

生成已完成,但出现错误。

We can see this at L49 of windivert.h.

#define __out

It seems that this line broke the STL by replacing ALL __out to nothing

Also, the snippet will succeed to compile if I add the following before the tail of include guard (I mean #endif /* __WINDIVERT_H */):

#undef __in
#undef __in_opt
#undef __out
#undef __out_opt
#undef __inout
#undef __inout_opt
TsXor commented 1 year ago

I just literally froze when I saw hundreds of errors from \<vector>.

My suggestion is defining all proprietary things with __windivert_ prefix.

basil00 commented 1 year ago

From memory, the __in/__out annotations are from Microsoft header files. But these annotations do not exist in MinGW, so the #undefs attempt to "remove" the annotations. However, this seems to clash with some C++ headers which happen to use these names as variable names.

The fix maybe is to just remove the annotations completely from windivert.h.

TsXor commented 1 year ago

From memory, the __in/__out annotations are from Microsoft header files. But these annotations do not exist in MinGW, so the #undefs attempt to "remove" the annotations. However, this seems to clash with some C++ headers which happen to use these names as variable names.

The fix maybe is to just remove the annotations completely from windivert.h.

I just checked my MSVC and MinGW installation, and they both have a header called sal.h. In that header, they defined such semantic annotations. Something like _In_, _Out_, _Inout_ is available. It's included in windows.h, so we can use it freely as everyone is supposed to avoid this.

(In the sal.h there is a FIXME telling this:)

/* FIXME: __in macro conflicts with argument names in libstdc++. For this reason,
 * we disable it for C++. This should be fixed in libstdc++ so we can uncomment
 * it in fixed version here. */
#if !defined(__cplusplus) || !defined(__GNUC__)
#define __in
#define __out
#endif

btw, we only need to include the following files in windivert.h after all

#include <minwindef.h>
#include <minwinbase.h>
#include <sal.h>