对于64位应用程序,.NET使用WSAStartup是安全的吗?

对于64位应用程序,.NET Framework版本与WSAData结构的本机Win32版本之间存在不匹配,因为字段的顺序不同。 我复制了.NET版本,用于我们基于C#的产品,同事担心我的内存损坏。 使用DllImport / PInvoke时,由于这种不匹配,是否存在内存损坏的风险? 将本机版本封送到托管版本时是否存在无效内存访问风险? 我们假设我并不关心实际访问生成的WSAData对象的字段。 我只是想确定我对WSAStartup的调用不会破坏内存或使应用程序崩溃。

这是WinSock2.h中的本机C ++版本。 请注意,成员的顺序在64位与32位之间是不同的。 WSADESCRIPTION_LEN为256,WSASYS_STATUS_LEN为128。

typedef struct WSAData { WORD wVersion; WORD wHighVersion; #ifdef _WIN64 unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; #else char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; #endif } WSADATA, FAR * LPWSADATA; 

以下是.NET Framework中的托管版本 :

 [StructLayout(LayoutKind.Sequential)] internal struct WSAData { internal short wVersion; internal short wHighVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=257)] internal string szDescription; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=129)] internal string szSystemStatus; internal short iMaxSockets; internal short iMaxUdpDg; internal IntPtr lpVendorInfo; } [DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)] internal static extern SocketError WSAStartup( [In] short wVersionRequested, [Out] out WSAData lpWSAData ); 

当然,这是不正确的。 .NET Framework摒弃它,结构大小仍然正确(32位模式下为400字节,64位模式下为408),因此不会发生内存损坏。 并且它实际上并没有使用任何返回的信息,如果他们这样做,他们肯定会抓住这个bug。

你可以在connect.microsoft.com上提交bug,我怀疑他们是否会急着解决它。

是的,结构错了……您可以使用错误的结构和正确的结构进行测试:

 [StructLayout(LayoutKind.Sequential)] internal struct WSAData { internal short wVersion; internal short wHighVersion; internal short iMaxSockets; internal short iMaxUdpDg; internal IntPtr lpVendorInfo; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)] internal string szDescription; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)] internal string szSystemStatus; } WSAData data; int res = WSAStartup(2 << 8 | 2, out data); Console.WriteLine("64bits: {0}, Result = {1}, szDescription: {2}, szSystemStatus: {3}", Environment.Is64BitProcess, res, data.szDescription, data.szSystemStatus); 

但是你没有任何问题,因为.NET可能不会使用所有这些不同的字段(它需要什么描述?)甚至没有Unicode转换的问题,因为使用的方法是Ansi one( CharSet=CharSet.Ansi ),每个Ansi字符都是Unicode中的合法字符。