mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2026-03-10 00:13:36 +08:00
fix(work): 修复指针 Double Free 问题
This commit is contained in:
+2
-3
@@ -32,8 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
|||||||
public static extern void FreeSlice([In] IntPtr slice);
|
public static extern void FreeSlice([In] IntPtr slice);
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
|
public static extern IntPtr GetContentFromSlice([In] IntPtr slice);
|
||||||
public static extern string GetContentFromSlice([In] IntPtr slice);
|
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int GetSliceLen([In] IntPtr slice);
|
public static extern int GetSliceLen([In] IntPtr slice);
|
||||||
@@ -45,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
|||||||
public static extern void FreeMediaData([In] IntPtr mediaData);
|
public static extern void FreeMediaData([In] IntPtr mediaData);
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern string GetOutIndexBuf([In] IntPtr mediaData);
|
public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData);
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern IntPtr GetData([In] IntPtr mediaData);
|
public static extern IntPtr GetData([In] IntPtr mediaData);
|
||||||
|
|||||||
+2
-3
@@ -42,8 +42,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
|||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
|
public static extern IntPtr GetContentFromSlice([In] IntPtr slice);
|
||||||
public static extern string GetContentFromSlice([In] IntPtr slice);
|
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
@@ -59,7 +58,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
|||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
public static extern string GetOutIndexBuf([In] IntPtr mediaData);
|
public static extern IntPtr GetOutIndexBuf([In] IntPtr mediaData);
|
||||||
|
|
||||||
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLL_NAME, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
||||||
|
{
|
||||||
|
internal static class MarshalerHelper
|
||||||
|
{
|
||||||
|
public static string PtrToStringAnsi(IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
return default!;
|
||||||
|
|
||||||
|
return Marshal.PtrToStringAnsi(ptr)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PtrToStringUTF8(IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
return default!;
|
||||||
|
|
||||||
|
#if NETCOREAPP || NET5_0_OR_GREATER
|
||||||
|
return Marshal.PtrToStringUTF8(ptr)!;
|
||||||
|
#else
|
||||||
|
byte b;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
b = Marshal.ReadByte(ptr, offset);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
while (b != 0);
|
||||||
|
|
||||||
|
byte[] bytes = new byte[offset - 1];
|
||||||
|
Marshal.Copy(ptr, bytes, 0, bytes.Length);
|
||||||
|
return Encoding.UTF8.GetString(bytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance.InteropServices
|
|
||||||
{
|
|
||||||
internal sealed class UTF8Marshaler : ICustomMarshaler
|
|
||||||
{
|
|
||||||
private static readonly Lazy<UTF8Marshaler> _instance = new Lazy<UTF8Marshaler>(() => new UTF8Marshaler());
|
|
||||||
|
|
||||||
public static ICustomMarshaler GetInstance(string pstrCookie)
|
|
||||||
{
|
|
||||||
return _instance.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? PtrToStringUTF8(IntPtr pNativeData)
|
|
||||||
{
|
|
||||||
return _instance.Value.MarshalNativeToManaged(pNativeData) as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntPtr MarshalManagedToNative(object managedObj)
|
|
||||||
{
|
|
||||||
if (managedObj is null)
|
|
||||||
return IntPtr.Zero;
|
|
||||||
if (!(managedObj is string))
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
|
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes((string)managedObj);
|
|
||||||
IntPtr pNativeData = Marshal.AllocHGlobal(bytes.Length + 1);
|
|
||||||
Marshal.Copy(bytes, 0, pNativeData, bytes.Length);
|
|
||||||
Marshal.WriteByte(pNativeData, bytes.Length, 0);
|
|
||||||
return pNativeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
|
||||||
{
|
|
||||||
if (pNativeData == IntPtr.Zero)
|
|
||||||
return default!;
|
|
||||||
|
|
||||||
#if NETCOREAPP || NET5_0_OR_GREATER
|
|
||||||
return Marshal.PtrToStringUTF8(pNativeData)!;
|
|
||||||
#else
|
|
||||||
byte b;
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
b = Marshal.ReadByte(pNativeData, offset);
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
while (b != 0);
|
|
||||||
|
|
||||||
byte[] bytes = new byte[offset - 1];
|
|
||||||
Marshal.Copy(pNativeData, bytes, 0, bytes.Length);
|
|
||||||
return Encoding.UTF8.GetString(bytes);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CleanUpManagedData(object managedObj)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CleanUpNativeData(IntPtr pNativeData)
|
|
||||||
{
|
|
||||||
if (pNativeData == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTICE:
|
|
||||||
* 这里释放内存会导致外部 P/Invoke 调用 FreeSlice() 方法时抛出异常
|
|
||||||
* 因此请注释下面的代码
|
|
||||||
*/
|
|
||||||
// Marshal.FreeHGlobal(pNativeData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetNativeDataSize()
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -129,10 +129,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
|||||||
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
||||||
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
||||||
// throw new PlatformNotSupportedException();
|
// throw new PlatformNotSupportedException();
|
||||||
string dataContent = /* 获取聊天记录数据内容 */
|
IntPtr dataContentPtr = /* 获取聊天记录数据内容 */
|
||||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
||||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
|
string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr);
|
||||||
|
|
||||||
response = JsonSerializer.Deserialize<Models.GetChatRecordsResponse>(dataContent);
|
response = JsonSerializer.Deserialize<Models.GetChatRecordsResponse>(dataContent);
|
||||||
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
||||||
@@ -220,10 +221,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
|||||||
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
// IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetSliceLen(dataPtr) :
|
||||||
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
// IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetSliceLen(dataPtr) :
|
||||||
// throw new PlatformNotSupportedException();
|
// throw new PlatformNotSupportedException();
|
||||||
string dataContent = /* 获取聊天记录数据内容 */
|
IntPtr dataContentPtr = /* 获取聊天记录数据内容 */
|
||||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetContentFromSlice(dataPtr) :
|
||||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetContentFromSlice(dataPtr) :
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
|
string dataContent = MarshalerHelper.PtrToStringUTF8(dataContentPtr);
|
||||||
|
|
||||||
response = JsonSerializer.Deserialize<Models.DecryptChatRecordResponse>(dataContent);
|
response = JsonSerializer.Deserialize<Models.DecryptChatRecordResponse>(dataContent);
|
||||||
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
response.RawBytes = Encoding.UTF8.GetBytes(dataContent);
|
||||||
@@ -293,7 +295,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
|||||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetData(dataPtr) :
|
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetData(dataPtr) :
|
||||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetData(dataPtr) :
|
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetData(dataPtr) :
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
string dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */
|
IntPtr dataNextBufferIndex = /* 获取媒体文件数据内容缓冲标识 */
|
||||||
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetOutIndexBuf(dataPtr) :
|
IsRunOnWindows() ? FinanceDllWindowsPInvoker.GetOutIndexBuf(dataPtr) :
|
||||||
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetOutIndexBuf(dataPtr) :
|
IsRunOnLinux() ? FinanceDllLinuxPInvoker.GetOutIndexBuf(dataPtr) :
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
@@ -304,10 +306,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.SDK.Finance
|
|||||||
|
|
||||||
byte[] bytes = new byte[dataSize];
|
byte[] bytes = new byte[dataSize];
|
||||||
Marshal.Copy(dataContentPtr, bytes, 0, bytes.Length);
|
Marshal.Copy(dataContentPtr, bytes, 0, bytes.Length);
|
||||||
Marshal.FreeHGlobal(dataContentPtr);
|
|
||||||
|
|
||||||
response.FileBufferBytes = bytes;
|
response.FileBufferBytes = bytes;
|
||||||
response.NextBufferIndex = dataNextBufferIndex;
|
response.NextBufferIndex = MarshalerHelper.PtrToStringAnsi(dataNextBufferIndex);
|
||||||
response.IsFinished = dataIsFinishFlag != 0;
|
response.IsFinished = dataIsFinishFlag != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user